数组双指针法汇总

指针移动方向:相向夹逼,同向移动

维护的是一个区间还是只是关心指针指向的两个元素

同向移动的、维护一个区间的双指针法即滑动窗口法,

2Sum

排序后两头往中间夹逼的双指针法。指针为什么可以不回退?即为什么可以i只++, j只--?

当A[i]+A[j]<sum的时候,为什么只需要考查i++,而不用j++?因为j是从j+1来的,与A[j+1]对应的左边元素A[k] (k<=i) 比A[i]小,结果都超了sum,才到的A[j],所以A[j+1]加上现在的A[i]必然超sum,故而不用考虑。


2MinusCloset: 寻找两个数,其差值最接近給定值target

排序后,同向移动的双指针法。

当A[j]-A[i]>target 时候,为什么只需要i++, 而不需要j--? 因为j-1的时候对应的A[i]比现在的A[i]要小,结果小于target才j++,如果用A[j-1]对应现在的A[i]差值会更小,故而不用再看了

int towMinusClosest(vector<int> &A, int target) {
	assert(A.size() > 1);
	int i = 0, j = 1, closest = A[1] - A[0];
	for (; j < A.size();) {
		if (abs(A[j] - A[i] - target) < abs(closest - target))
			closest = A[j] - A[i];
		if (closest == target) break;
		if (A[j] - A[i] > target) {
			++i;
			if (i == j) ++j;
		}
		else ++j;
	}
	return closest;
}

subarray sum (all positive)  不需要有序

滑动窗口法。

可以这样理解:枚举起点为i的子数组,j不断往后推,当超过sum的时候就没必要继续枚举了,起点为i的子数组枚举结束,枚举起点为i+1的子数组,这里重点是,j不用回退,因为A[i]+..+A[j-1] < sum,则A[i+1]+...+A[j-1] 少了一个正数A[i]必然也小于 sum,所以j不用回退。

def f(a, t):
    l, r, curSum = 0, 0, a[0]
    while r < len(a):
        if curSum == t: 
            print a[l : r + 1]
            r += 1
            if r < len(a): curSum += a[r]
        elif curSum > t:
            curSum -= a[l]
            l += 1
        else: 
            r += 1
            if r < len(a): curSum += a[r]


对于排序数组的2sum,有一个扩展:两个数组A,B,要求2sum的两个数从A、B中各取一个

解法:两遍双指针夹逼法,1)A[0] vs B[n -1],2)A[n-1] vs B[0]


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值