Open TommyCpp opened 6 years ago
https://leetcode.com/problems/intersection-of-two-arrays/description/
使用Python中的字典key作为set
(因为似乎不能直接使用set
)
https://leetcode.com/problems/minimum-distance-between-bst-nodes/description/
BST的中序遍历基本步骤
定义一个递归函数dfs
void dfs(TreeNode root) {
if (root == null) return;
dfs(root.left);
if (prev != null)
result = Math.min(result, root.val - prev); // prev and result is variable subject to class
prev = root.val;
dfs(root.right);
}
https://leetcode.com/problems/sum-of-left-leaves/description/ 此题的关键是对于左子树和右子树有不同的迭代策略,所以要有两个迭代函数
class Solution {
public int sumOfLeftLeaves(TreeNode root) {
if (null == root) {
return 0;
}
return this.sumOfLeftLeaves(root.left, true) + this.sumOfLeftLeaves(root.right, false);
}
private int sumOfLeftLeaves(TreeNode root, boolean isLeft) {
if (null == root) {
return 0;
}
if (root.left == null && root.right == null) { //找出所有叶子节点,通过函数的isLeft判断是不是左叶子
return isLeft ? root.val : 0;
}
return this.sumOfLeftLeaves(root.left, true) + this.sumOfLeftLeaves(root.right, false);
}
}
https://leetcode.com/problems/convert-bst-to-greater-tree/description/ 中序遍历,同时累计BST树中的所有数之和
https://leetcode.com/problems/sum-of-two-integers/description/
class Solution {
public int getSum(int a, int b) {
if(b == 0){//当进位被消耗完的时候退出
return a;
}
int next = a & b; //当且仅当a,b都是1的时候才进一位
next <<= 1; //进一位
a = a ^ b; //当且进当a,b中一个0一个1的时候才出现1
return getSum(a,next); //
}
}
https://leetcode.com/problems/first-unique-character-in-a-string/description/ 除了使用counter API之外,还可以使用str的count函数
class Solution:
def firstUniqChar(self, s):
"""
:type s: str
:rtype: int
"""
letters = "abcdefghijklmnopqrstuvwxyz"
unique = [s.index(l) for l in letters if s.count(l) == 1]
return -1 if len(unique) == 0 else min(unique)
https://leetcode.com/problems/escape-the-ghosts/description/ 题目的关键是理解 只要有Ghost能够在你之前到达Target,你就一定会失败 因此只要对比Target到原点距离和Ghost到Target之间距离即可
https://leetcode.com/problems/minimum-ascii-delete-sum-for-two-strings/description/
我们使用a1,a2
表示当前s1, s2
的子串,最终目标是使得a1 == a2
并且删除的字符ASCII值最小
dp[i][j]
表示针对s1[:i],s2[:j]
的答案
dp[0][0] = 0
dp[i][0]
表示只有s1
中有字符,此时可以得到dp[i][0] = dp[i - 1][0] + ord(s1[i - 1])
dp[0][i]
表示只有s2
中有字符,此时可以得到dp[0][i] = dp[0][j - 1] + ord(s2[j - 1])
s1[i - 1] = s2[j - 1]
, 则dp[i][j] = dp[i - 1][j - 1]
dp[i][j] = dp[i - 1][j] + ord(s1[i-1])
dp[i][j] = dp[i][j - 1] + ord(s2[j-1])
`dp[i][j] = dp[i - 1][j - 1 ] + ord(s1[i-1]) + ord(s2[j - 1])
https://leetcode.com/problems/lemonade-change/description/ 注意在该场景中,针对20的情况有两种不同的找钱方案:
https://leetcode.com/problems/two-sum-iv-input-is-a-bst/description/
创建一个数组values
用于记录BST中节点的值,
递归的扫描节点,如果k-root.val
,即当前值与目标值的差值在values
里面,则返回True
否则,values
记录当前节点,继续搜索
但是此处没有利用BST中左右子树值的确定关系
https://leetcode.com/problems/count-binary-substrings/description/
设置两个标记cur
, last
从第2个字符开始遍历字符串s
当字符i
与字符i-1
不同的时候,我们可以判定此处发生了0/1转变,例如0010
,当i=2
的时候发生转变,此时cur=2
,last=0
我们将cur
的值赋给last
,同时将cur
重新设定为1
然后进行一个判断last >= cur
是否为true
true
,说明至少存在一个符合条件的substring,结果+1false
,则继续循环https://leetcode.com/problems/keys-and-rooms/description/
使用一个opened
数组来记录各个房间是否打开过
依次打开所有没有打开过的房间,如果房间里的钥匙可以打开尚未打开的房间,则继续
否则返回,
判断此时是否所有房间都打开过
本质上来说,这是一个图遍历问题,钥匙对应图的邻居
https://leetcode.com/problems/total-hamming-distance/description/
0~10^9
,基本可以认为相当于32位int
的范围,因此可以使用32次循环来获得每个bit位https://leetcode.com/problems/binary-tree-tilt/description/
首先构造一个SumTree用于记录每个节点所有子节点的和,然后再计算每个节点的tilt
https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/description/ 注意给出的数组的特殊性质:排序数组 考虑从头尾设置两个指针,分别指向最大值和最小值 由于题目保证有且仅有一个解,所以通过调整头尾两个指针的位置一定能够得到结果
如果两个指针相加值小于target,则我们需要减小两个指正相加的值,因此,将尾指针向前移动 如果两个指针相加值大于target,则我们需要减小两个指正相加的值,因此,将头指针向后移动
可以不设置循环跳出条件(即可以设置为while(true)
),然后在循环中等到头尾指针相加等于target的时候break
即可
https://leetcode.com/problems/add-two-numbers/description/
注意这样几点:
5+5 = 10
的情况)https://leetcode.com/problems/remove-nth-node-from-end-of-list/description/
给定两个指针p,q
第一步,让q
移动N
个位置
第二步,让p,q
同时向后移动,直到q
移动到最后一个节点为止
此时p.next
就是需要被删除的节点
q
应当已经为null。可以在第一步和第二步之间加一个判断,如果此时q
为null,则直接返回head.next
即可https://leetcode.com/problems/swap-nodes-in-pairs/description/
思考使用递归完成,
针对A->B->C->D.....
的情况,首先交换好C,D
及之后的节点,此时链表为A->B->D->C....
,然后将B.next = A
,A.next = D
完成交换
https://leetcode.com/problems/rotate-list/description/
k
超过链表长度s
的时候,其结果应当与k%s
相同t
,使得在结果链表中t.next = null
,原链表中t.next
作为结果链表的headt
应当是第count - k
个节点,其中count
是链表长度https://leetcode.com/problems/partition-list/description/
注意每一轮迭代之后必须将当前节点的next
置为null
,否则会造成循环链表
https://leetcode.com/problems/convert-sorted-list-to-binary-search-tree/description/ 递归的解决问题,使用两个指针来确定中间节点,注意如果节点数量是偶数的时候应当如何处理
https://leetcode.com/problems/remove-linked-list-elements/description/
注意考虑最后一个元素等于val
的情况
https://leetcode.com/problems/middle-of-the-linked-list/description/ 基本操作,找到链表中点。
runner
和walker
runner
每次移动两个节点,walker
每次移动一个节点runner
的结束条件,防止出现NullPointerException
https://leetcode.com/problems/counting-bits/description/
2**n
中1
个个数肯定为1(因为他们的二进制都是类似100000....
的模式)2**n
与2**n + 2**(n-1)
之间的数,1
的个数都是2(因为他们的二进制都是类似1001,1010,1100
的模式)n & (n - 1) != 0
(即n
不是2的指数),则其1
的个数应当等于1+n - 2**(log(n) / log(2))
https://leetcode.com/problems/flatten-binary-tree-to-linked-list/description/
注意题目要求 in-place的进行转换,所以需要保存下root
的左右子树,然后逐个进行flatten
,最后将左子树的结果拼接到root
的右子树上,再将右子树的结果拼接之后
https://leetcode.com/problems/minimum-time-difference/description/
min
函数进行每一轮最小化操作可以提高效率23:00
到00:00
的情况,可以将排序后列表的第一项加到列表最后https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/description/ 基于层次遍历,使用一个栈保存所有节点的子节点,然后依次出栈。
reverse
Collections.reverse()
来进行reverse
操作https://leetcode.com/problems/reverse-bits/description/
使用n & 1
取得每一位,如果是0,则res<<=1;
,如果是1,则res+1;res<<=1
,之后将n >>>= 1;
注意n
必须无符号右移
https://leetcode.com/problems/longest-common-prefix/description/ 先进行排序,这样Prefix相同的字符串会排序到一起,这时候只要对比第一个和最后一个字符串即可
https://leetcode.com/problems/zigzag-conversion/description/
通过观察,发现周期是2*n-2
,在这个周期中,前n
个元素不需要调整,直接放入对应行即可。后n - 2
个元素需要从倒数第二行到第二行逐个填充,因而使用公式2*n - i - 2
来计算对应行数
https://leetcode.com/problems/binary-tree-postorder-traversal/description/
题目要求使用迭代方法处理,
思路是使用一个栈stack
存储节点,使用一个栈res
存储结果(但是是反向的)
思考,后序遍历的反向是什么? 是root,right,left
因此,在每一轮迭代中,我们的目标是逐个向res
中压入root, right, left
因此在stack
不空的情况下
p = stack.pop();
res.add(p.val);
if(p.left != null){
stack.add(p.left); //注意这里必须是先压入左节点
}
if(p.right != null){
stack.add(p.right);
}
https://leetcode.com/problems/validate-binary-search-tree/description/
使用中序遍历整个二叉树肯定能得到一个递增数组,基于这个条件可以判断
在递归函数中保持两个变量max
和min
,分别表示该子树节点的上界和下界,然后判断当前root
节点是否在其中,之后继续递归
https://leetcode.com/problems/edit-distance/description/
注意DP的范围是一个有word1.length()+1
行,word2.length()+1
列的数组
子问题是word1
的前i
项,word2
的前j
项的编辑距离,记为d(i,j)
状态转移方程是d(i,j) = min[d(i - 1,d), d(i,j - 1), d(i -1,j -1)] + 1
https://leetcode.com/problems/symmetric-tree/description/
left.right
and right.left
以及 right.left
and left.right
是否对称https://leetcode.com/problems/longest-substring-without-repeating-characters/description/
使用两个指针i
,j
来表示符合要求的子串,从头到尾遍历,如果str[j]
不在Set
中,则j++
;如果在,则i++
直至str[j]
不在Set
中
https://leetcode.com/problems/single-number-ii/description/
当数字第一次出现的时候,它被记录在b
中,此时a
中对应bit位是0;
当数字第二次出现的时候,它被记录在a
中,此时b
中对应bit位是1;此步骤清空b
中对应bit位的1
当数字第三次出现的时候,此时a
中的数值被清空
最后出现两次的数在a
或者b
中,所以使用a|b
https://leetcode.com/problems/heaters/description/
houses[i] < heaters[0]
和 houses[j] > heaters[heaters.length - 1]
的情况houses
和heaters
的开始位置,依次排查,直到houses[i] > heaters[t] && houses[i] < heaters[t + 1]
的情况houses[i]
和heaters[t], heaters[t + 1]
的相对关系,取较大值https://leetcode.com/problems/merge-intervals/description/
start
对数组进行排序j
j + 1
开始,继续迭代https://leetcode.com/problems/binary-tree-longest-consecutive-sequence/description/
root.val - 1
and the cur=0
cur
must be reset to 1 - 1 = 0
cur = 1
https://leetcode.com/problems/gas-station/description/
start
和end
,分别指向gas.size()-1
和0
sum
记录此时燃油剩余,初始为gas[end] - cost[end]
sum > 0
的时候,我们不断将end++
,同时更新sum
sum < 0
的时候,我们开始start--
,同时更新sum
start
与end
会和sum
,如果大于0,则返回start
,否则不能走完一圈
496. Next Greater Element I
https://leetcode.com/problems/next-greater-element-i/description/ 维护一个Map用于存储每个字母对应的结果