some tips
双指针的用法相对灵活的。
- 可以归纳为以下几种:
- →→
- → ←
- ←←
- ←→
- 另一种情况是两个数组,一个数组一个指针
- 都需要注意是否需要排序的问题
哈希表:空间换时间
注意哪些可以作为key,哪些不可以
题目
18. 四数之和 \ 454. 四数相加 II
这种二数和、三数和、四数和都可以用双指针、哈希表。但复杂度会一直增加。需要做一些优化。
169. 多数元素 \ 229. 求众数 II
可以用投票法,就是看做候选人,不一样的就扣。
658. 找到 K 个最接近的元素
这就是←→双指针的用法,先用二分法找到,然后开始左右移动。
75. 颜色分类
也是用两个指针来定位元素的位置,还要有一个指针来确定当前检查的颜色。
11. 盛最多水的容器
→ ←双指针的用法,需要判断移动的条件,即短的动(容量有限)
42. 接雨水【困难、重要】
双指针:
- 可以根据行来计算。
- 两个指针,逐个检查。比较的对象是当前左边最大,和当前右边最大。小了就会积水。
动态规划:
分享一个不错题解作者的理解:
maxleft[i] 表示第 i 个柱子左边最高柱子的高度,同理 maxright 也一样。这个其实和方法三的思路是一样的,只是方法三不用动态数组了,而是使用一个变量,这样可以减少空间的使用。所谓动态规划就是出现一些重叠子问题时,我们事先记住它。比如我问 1+1+1+1+1 等于几时,你会回答是 5,如果我说再➕1呢,你肯定会脱口而出是6。之所以脱口而出是因为i你在计算时记住了前面的结果是5,而不是重新计算一遍。
本题也一样,我们对于每次柱子 i,都要重新遍历它的左边和右边来分别寻找两边最高的柱子,这样对于每个 i 我们会重复比较,导致时间复杂度变大。因此我们的解决办法是利用一个 maxleft 和 maxright,maxleft【i】就表示 i 左边最高的柱子高度是 maxleft【i】。。。
当maxleft和maxright填满以后,我们重新遍历一遍,这时对于每一个 i 都可以通过直接查询这两个数组获得两边最高的高度,而不必浪费时间反复寻找。
219. 存在重复元素 II
就是创建一个字典,记录key是元素,value是索引。然后判断索引差
220. 存在重复元素 III
- 暴力法:
维护一个长度为k的窗口,逐一比较。
存在冗余运算,无法通过 - 桶排序的思想
将数组中的值经过映射变成key放入桶中。
保证只需要在当前桶和相邻桶进行比较是否小于等于t。
对于索引,只需要定期清理桶中过期的值即可。
对于dict。可以用key是否in来判断,key in dict, dict.pop(key) - 二叉搜索树(to do)
560. 和为K的子数组
暴力法很容易想到,但超时间。
想过用双指针(滑动窗口),但是这种没序,又要求连续,不好处理指针移动,试了下很麻烦,没做出来。
学了一个新的,前缀和。
也就是
s
u
m
(
n
u
m
s
[
i
:
j
]
)
=
s
u
m
(
n
u
m
s
[
:
j
]
)
)
−
s
u
m
(
n
u
m
s
[
:
i
]
)
sum(nums[i:j]) =sum(nums[:j]))-sum(nums[:i])
sum(nums[i:j])=sum(nums[:j]))−sum(nums[:i])