![](https://img-blog.csdnimg.cn/20201014180756913.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
双指针
abant2
世界上最菜的arcem
展开
-
leetcode 215 第k大元素
解法一:维度大小为k的堆复杂度: O(lNogK)O(lNogK)O(lNogK)解法二:快速选择快排其实还是有挺多细节的,1 必须是右边的哨兵先走,因为要保证最后停在偏小的位置上,然后让哨兵和他交换位置。2 递归终止条件可以设置为 l >= r,可以保证一个元素,或者出错时能停止。class Solution {public: void qChoose(vector<int> &nums, int k, int l, int r) {原创 2021-07-26 18:03:39 · 78 阅读 · 0 评论 -
leetcode 75 只有三个数的数组排序
此题两次遍历很容易做,并且能满足O(1)空间,只要存每个数个数,然后填充即可。此题比较难的是一次遍历的解法,这里我们使用双指针来做。由于我们希望前面都是0,后面都是2,所以用两个指针来维护头和尾,放置0和2.遍历每个元素,如果是2,就放到后面,但是这里可能会遇到2和2交换的情况,所以我们用while来持续放置。如果是0,那么我们直接交换即可。0不用循环,因为2不到后面不行,但是0肯定要遍历到才会交换。class Solution {public: void sortColors(vect.原创 2021-07-25 16:12:12 · 245 阅读 · 0 评论 -
leetcode 11 最多水的容器
这题和接雨水非常的像啊,但考虑的是两个柱子间能接的最多水。在接雨水问题中,我们可以通过双指针维护两边的最大值得到每个柱子上面的水量。因为接雨水求的是两边最大值的最小值。考虑此题的暴力做法,由于只需要考虑两根柱子,所以O(N2)O(N^2)O(N2)肯定可以解决。考虑完暴力做法你会发现,此题和接雨水没有半毛钱关系,建模也完全不一样。接下来直接给出此题解法:双指针,无需维护最大值,考虑两个指针大小,小的往中间移道理:此种解法相当于排除了大的移动的可能性。咱们假设左边小,右边大,那此时左边的已经没有.原创 2021-07-17 21:38:40 · 87 阅读 · 0 评论 -
leetcode 18 四数之和
此题是三数之和的升级版,相比三数之和细节更多。首先,还是三数之和的套路,数越多越只能暴力,比起三数之和就是加了层循环。然后就是剪枝,在外层循环中,如果碰到之前见过的数,就一定要剪枝。class Solution {public: vector<vector<int>> fourSum(vector<int>& nums, int target) { vector<vector<int>> ans;原创 2021-07-13 15:50:10 · 48 阅读 · 0 评论 -
leetcode 15 三数之和
多数问题还是排序来做比较好,先排序,然后对每个数字,在右边找剩下的两个。这里就是另一个问题了,如何在已排序数组中找到所有的两数之和可能性?在这个子问题中,双指针是非常好的一个思路。分别用指针指向最大的数和最小的数,大了就右指针左移,小了就左指针右移,都没问题就两个一起动。typedef tuple<int, int, int> T;class Solution {public: vector<vector<int>> threeSum(vector<原创 2021-07-13 14:58:17 · 69 阅读 · 0 评论 -
leetcode 1610 极角序+双指针+环形问题
此题算是一个比较明显的双指针题了,而且是确定最大窗口的那种,只要一个if的那种。困难的是对二维空间的建模,这里用atan2进行极角排序,从-180度开始,每转一圈加360度。对于环状问题,让数组等于两倍自己即可。typedef vector<int> V;class Solution {V start;public: double get_arc(vector<double> v) { return atan2(v[2]-start[1], .原创 2021-07-09 18:57:17 · 86 阅读 · 0 评论 -
leetcode 493 满足大小关系的对 分治
注:此题与327题很相似。解法一:分治直接考虑,如果是两个有序数组,O(N)能不能做,用单指针明显可以,同327题。故直接分治解决。typedef long long ll;class Solution {public: void msort(vector<int>& nums, int& sum, int l, int r) { if(l == r)return; int mid = l + (r-l)/2;原创 2021-04-15 12:22:11 · 90 阅读 · 0 评论 -
leetcode 327 特殊分治 双指针 线段树
解法一:分治 O(NlogN)这个题用分治做其实很难想。对于求区间和问题,前缀数组很有用。但这个题要求所有区间范围,如果枚举需要O(N2)O(N^2)O(N2),其实也可以接受。用分治的话,其实就是想明白了一件事,只要确保i < j,i,j在哪个位置其实是不影响结果的,因为我们只需要求区间个数。这就很好办了,分治就是划分,然后处理两个有序数组。利用分治可以很容易得到所有上述数组,用O(N)时间计算区间个数+合并即可。在计算区间个数时,可以用到双指针。对第二个有序数组,咱们可以用双指针确定它的最小原创 2021-04-14 20:58:30 · 110 阅读 · 0 评论 -
leetcode 1658 将 x 减到 0 的最小操作数 双指针+前后缀和 全两种做法
这是京东周赛的第三题,没做出来也是不太高兴。这题我一开始想的是dp,其实是个锤子dp。大概我的做法就是右边每去除一个元素,左边都枚举一下,O(N^2)的复杂度,然后就无限超时。。还有种做法是双指针,左边固定,移动右边,满足条件就停或者移动左边,最坏也是N方的复杂度,但好像是能过的。最强的做法是O(N)的,即看到这类连续子序列求和问题,最好是存前缀和的。此题存一个左前缀和和一个右前缀和即可。对每一个左边序列,判断另一个在不在右前缀里。(这不是TwoSum吗。。。。太笨了)class Solution:原创 2020-11-15 14:57:17 · 327 阅读 · 0 评论 -
leetcode 283 移动零 单指针方法
题解是双指针,但其实单指针就足够了。每次遍历把零元素存起来,这样交换后交换的零元素也在后面,一次遍历就可以结束。from collections import dequeclass Solution: def moveZeroes(self, nums: List[int]) -> None: """ Do not return anything, modify nums in-place instead. """ zeros原创 2020-11-19 09:49:54 · 88 阅读 · 0 评论 -
leetcode 424 双指针模板
每次一遇见双指针就头疼,主要还是模板不到位。就像二分一样,有一个好的模板事半功倍。这次也看到了一个好的双指针模板:右边每次只动一个,到最右就停止。左边看条件动,用counter统计区间条件。双指针一般对应区间问题,此题可理解为选一个最大区间,里面最多出现的元素不少于n-k个,之后用双指针就非常舒服了。class Solution: def characterReplacement(self, s: str, k: int) -> int: N = len(s)原创 2021-02-02 18:28:09 · 194 阅读 · 0 评论 -
leetcode1208 双指针 维护最大窗口
双指针问题一般左边需要不停移动知道满足规律,但在这个最大窗口问题中,可以不让左边的一直移动,只要每次移动一次即可。设置默认窗口大小为0,如果不动,就维持窗口,这样能维持住最大窗口,最后只要返回左右指针的差即可。相比普通的双指针能减少一半左右的时间。class Solution: def equalSubstring(self, s: str, t: str, maxCost: int) -> int: def getCost(c1, c2): retu原创 2021-02-06 13:02:10 · 113 阅读 · 0 评论 -
leetcode 978 波动连续数组双指针
要计算最长的波动连续数组,如果是子数组的话可以用dp,不过这个没必要。首先要知道,两个数是肯定没问题的,除非他们相等,所以从三个数开始,如果右边不满足了,就必须从新开始,所以双指针就用上了。class Solution: def maxTurbulenceSize(self, arr: List[int]) -> int: l, r = 0, 2 ret = min(2, len(Counter(arr))) while r < len原创 2021-02-08 18:23:34 · 132 阅读 · 0 评论 -
leetcode 992 双指针 区间个数
之前做的题,都是问区间最长长度或者最优结果,但这次返回的是满足条件得区间个数,就不能用之前的思路了,因为可能会忽略情况。第一种解法就是,在左指针移动前,先记录下满足条件的个数,代码如下:class Solution: def subarraysWithKDistinct(self, A: List[int], K: int) -> int: l, r, ret = 0, 0, 0 c = Counter() while r < len原创 2021-02-09 15:18:58 · 193 阅读 · 0 评论 -
leetcode 995 区间翻转问题,队列
思路一:滑动窗口首先考虑第一个位置,只有一个窗口能翻转它。所以第一个窗口必须满足第一个位置。然后再看第二个元素,只有第一,第二个窗口能满足,第一个窗口是否翻转是固定的,所以第二个窗口是否翻转也固定,这样窗口一直滑动,咱们只需关心窗口的第一个元素就好。class Solution: def minKBitFlips(self, A: List[int], K: int) -> int: ret = 0 for i in range(len(A)-K+1):原创 2021-02-18 16:49:09 · 177 阅读 · 0 评论 -
leetcode 395 双指针X 分治✔
这题一看太像双指针了,熟悉的子区间问题,但这次不太一样。熟悉的双指针模板这里是不适用的。所以本题应该用分治做。关键的点在于,如果在字符串里有一个字符,他总数小于k,那么,任何包含这个字符的子串都不满足条件。所以,咱们应该把这个字符剔除出去,这个是核心。代码如下:class Solution: def longestSubstring(self, s: str, k: int) -> int: c0 = Counter(s) if len(s) == 0: r原创 2021-02-27 15:32:36 · 190 阅读 · 0 评论 -
ZJ19 双指针 三个站点
这题一看题我当场暴力。。结果就超时。仔细一看题,发现中间那个没什么卵用。双指针是解决这题很好的方法,可以用来找左右边界。固定的双指针模板会每次固定右边界,所以咱们对左边的数组取2的组合即可。from math import factorialMOD = 99997867N, D = input().split(' ')N, D = int(N), int(D)builds = []o = input().split(' ')for c in o: builds.append(int(原创 2021-03-09 23:31:02 · 151 阅读 · 0 评论 -
leetcode 42 接雨水 单调栈+双指针
初始思路:单调栈这是个不太寻常的单调栈,但也是可以做的。思路是,如果一直递减,就留着。如果递增,看看左边有没有护着的,有就计数,没有就继续往左走。这样能循环的不断加较低的水坑,挺难想的其实。class Solution: def trap(self, height: List[int]) -> int: if not height: return 0 stack = [] ret = 0 for i, h i原创 2021-03-17 13:53:57 · 100 阅读 · 0 评论