two pointers

两个指针,想一想,能根什么联系上呢?

好像是这样,遍历数组时,我们在脑袋中模拟是不是用一个小指针,一次一次往后挪动。

用一个例子引入:给定一个递增的正整数序列和一个正整数M,求序列中的两个不同位置的数a 和 b,使得它们的和恰好为 M,输出所有满足条件的方案,例如给定序列{1, 2, 3, 4, 5, 6}和正整数M = 8 就存在 2 + 6 = 8,3 + 5 = 8;

以我们正常的思路很好想吧,不是先拿一个,然后再确定另一个嘛,如果是答案就输出,不是就跳过,很简单啊,没有什么难的把,时间复杂度是O(n^2),

找到高复杂度的原因。

1)对于一个确定的a【i】 来说,如果当前的a【j】满足a【i】+ a【j】> M 那在 j 之后的是不是都有 a【i】 + a【j+1】 >M?我们是不是可以直接跳过这些比较(由于序列递增)是不是节省了大量枚举的时间

2) 对于某个a【i】来说,如果 a【i】 + a【j】> M恰好成立,那么对于a【i+1】+ a【j】 > M成立,因此a【i+1】之后的就没有必要在比较了。

然后我们依据a【i】 + a【j】的3中情况去判断,两指针移动的位置。

  1. a【i】+a【j】== M,说明找到其中一组方案,由于序列递增,不等式a【i+1】+ a【j】 > M与a【i】+ a【j-1】 < M均成立,但是a【i+1】+a【j-1】与M的大小未知,因此剩余的方案只能在【i+1, j-1】中选择,这时我们令 i = i+1,j = j-1
  2. a【i】+a【j】> M, 由于序列递增,不等式a【i+1】+a【j】> M成立,但是a【i】+a【j-1】与 M未知,剩余可能的方案应该在【i,j-1】区间内产生,令j = j-1(令j移动)
  3. a【i】+a【j】< M,由于序列递增,不等式a【i】+a【j-1】< M成立,但是a【i+1】+a【j】与 M未知,剩余方案只能【i+1, j】的区间内产生,令 i = i+1(令i 移动。)

反复执行上述3个判断,直到 i >= j成立。

while(i < j){
	if(a[i] + a[j] == m){
		cout << i << " " << j << endl;
		i++;
		j--;
	}
	else if( a[i] + a[j] < m)
		i++;
	else
		j--;
}

这样  i 只有递增操作,j 只有递降操作,当循环 i >= j 时停止,i 和 j 的操作最多只有n次,时间复杂度降低为O(n)。可以发现,two pointer 思想就是充分利用了序列递增的性质,以很浅显的思想降低了时间复杂度。

然后我们看一下序列并归问题 ,两个递增序列A和B 合并为一个递增序列C,

同样的我们可以设置两个下标i 和j,初始值均为0,表示分别向序列A的第一个元素和序列B的第一个元素,然后根据A【i】和B【j】的大小来决定哪一个放入序列C。

1)A【i】 > B【j】那么B【j】放入序列C中,j++

2) A【i】 < B【j】那么A【i】放入序列C中,i++

3) A【i】 == B【j】任意,对应下标+1

int merge(int A[], int B[], int C[], int n, int m){
	int i = 0, j = 0, index = 0;
	while(i < n && j < m){
		if(A[i] < = B[j]){
			C[index++] = A[i++];
		}
		else
		{
			C[index++] = B[j++];
		}
	}
	while(i < n) C[index++] = A[i++];
	while(j < m) C[index++] = B[j++];
	return index;
}

总结

到底什么才是 two pointer 思想,其实我认为就是2个指针。

利用问题的本身,和序列的特性,使用两个下标 i、j 进行扫描,(可以同向扫,也可以反向扫),来降低时间复杂度。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值