LeetCode刷题记录——TwoPointers

不得不说,TwoPointer问题一道道的都是很有意思的。。。

763. Patition Labels

还算不错,需要遍历一遍拿到最右位置,然后是N的空间复杂度,N的时间复杂度。

524. Longest Word in Dictionary through Deleting

和703有一点像,需要先遍历一遍,这里需要存下一个字符出现的每一个位置。然后加了大量的trick。

287. Find he Duplicate Number

这道题思路也是很清奇了。首先先不考虑节点0,因为题目规定所有的节点的值的范围都在1到n范围内,因此1-n范围内必定形成环(证明方法类似于1自己不形成环,那么就要指向非1的数,假如指向2,然后为了不形成环,2不能指向1和2,类似的递推,n个点不形成环只能指向第n+1个节点),然后节点0由于题目要求一定指向1到你的某个节点。

881. Boats to Save People

排序,两个指针,一个指向当前最大的,一个指向当前最小的。

75. Sort Colors

考虑快排其实就是一个双指针问题,这道题就迎刃而解了,甚至更简单一些。第一遍划分为左边是0右边是非0,然后对右侧进行第二遍划分,划分为左边是1右边是2即可。

11. Container With Most Water

思路挺简单的,但就是自己想不到,尽管知道这是一道双指针问题但是并没有什么乱用……思路是维护两个指针,一个在头一个在尾,因为面积被两只之间较短的长度所限制,那么每次就将较短的指针往里面移动一位,这样是可能遇到面积变大的情况的,如果移动的是较长的指针,那么面积一定不会变大。

42. Trapping Rain Water

这道题是面试中遇到的一道题,当时的做法是Solution中的方法2,也算是DP,但是既然是双指针问题就会有更好的方法。Solution中给了一个一次遍历就得到解的方法,类似于11,维护左右两个指针,每次移动高度较小的那个指针,并且计算被移动的指针所在的位置所提供的水的多少,只需要和所在一侧的高度比较就行,原因在于每次移动的是较矮的一方,因此另一侧的高度肯定更高。

3. 3Sum

如果是2sum,那就是很明显的TwoPointer问题,复杂度是O(N),3SUM的话,就是加一个外层循环,内层是一个2Sum问题,这样该问题就可以在平方复杂度下解决。注意实现时,内层2Sum问题范围要缩小,为了避免重复元素,外层指针要指向下一个不同的元素。

16. 3Sum Closest

首先把问题转换为3sum+一个数与0最近的问题,与零最近的可能是正数也可能是负数,根据零值定理,并且已经将数组排序,所以right指针往右移直到遇见第一个非正数或者遇到left时就意味着刚刚踩上零值或者越过零值,此时判断一下就行,正常情况下,比较当前值和上一个sum谁离0更近就更新谁,当right遇到left或者right指向最后一个元素的时候特殊考虑一些边界条件。

18. 4Sum

80. Remove Duplicates from Sorted Array II

维护一个变量count,表示当前fast指针前面有几个连续相同元素,然后当count大于等于2的时候,就让fast快速前进到下一个新的元素,除非移动到末尾,这就是主要思想。

713. Subarray Product Less Than K

Sliding Window

可以考虑这么一个opt函数,接受一个值right,然后opt(right)返回满足要求的最(小)左的left,使得left到right这个区间的连乘积严格小于k,那么可以肯定的是这个opt函数是单调的(不是严格单调),因为nums中的元素都是正数。即当r1>r2时,opt(r1)>=opt(r2)。Solution中提到,有了这个性质之后,就可以考虑使用Sliding window了。因为此时可以保证window的两端都是始终向右移动的,此时可以保证O(N)的时间复杂度。

有了这个函数后,下一条原则也是难以发现的。。。就是对于所有的$$$r$$$,计算$$$r-opt(r)+1$$$的和,就可以得到结果。原因在于对于以r结尾的最大子串时,只需要计算包含r的即可,不包含r的在之前就被计算了,任意一个串[l,r]的计数都会被assign到r的计算中。

209. Minimum Size Subarray Sum

与713同理,注意的是改变一下自己的思路,slow,fast指针一定要是左包含,右不包含,这样代码写起来很整洁。

845. Longest Mountain in Array

我的做法是类似于42的做法,左扫描一遍右扫描一遍,left数组表左侧连续比当前元素小的长度,right数组类似,然后根据这两个数组可以求出最大的mountain。Solution中给的TwoPointers解法要更胜一筹因为只需要O(1)的空间复杂度。每次left指针指向可能的mountain的左边界,然后去找右边界,下次迭代让left追上right即可。

3. Longest Substring Without Repeating Characters

第一种方法是我一开始想到的方法,类似于524,设置一个表,通过这个表可以查到下一个该字符出现的位置,然后有了这个表之后用两个指针遍历字符串。left不断向右移动,right指向最小的table[left],直到两个指针重合。
然后看了Solution中的解法,还是只用两个指针,需要一个额外的hashtable保存当前left-right串口内的字幕频次。每次循环时看看right指向的字符在不在串口内,在的话就右移left,直到right指向的字符被移出去;不在的话直接更新词频,右移right。

567. Permutation in String

这道题的关键思想就是一点:一定要想到一个字符串是另一个字符串的permutation,意味着两个字符串的26个字母的频次相同,那么我们先统计s1的字符频次,然后用一个定长滑窗在s2上面滑,每滑动一次,就看看二者的频次表相不相同就可以了。然后一点优化就是每次比较词频表有一点浪费,比如这次滑动完全和字母a没关系,那么这次就不用考虑a的频次,每次滑窗内会移出最左字符,移入最右字符,那么维护着两个的字频变化就可以。用一个变量表示当前有多少个字母的词频一致,当这个变量等于26时,就是True了。

本站总访问量