算法思维__two pointers

算法基础__two pointers

Easy 级例题:给定一个递增的具有n个元素的正整数序列arr和一个正整数s,求序列中两个不同位置的数a和b,使他们的和恰好等于s,输出所有满足条件的结果ij。如序列arr = {1, 2, 3, 4, 5, 6}和正整数s = 9, 就有 4 + 5 和 3 + 6 。

本例最简单的方法就是利用二重循环枚举所有的可能性,得出结果。但是这样做的时间复杂度为O(n^2),显然是低效率的。
这里利用序列本身的特性和双指针two pointers的思想来解决这个问题。

  1. 对于一个确定的arr[i], 如果某个的arr[j]满足arr[i] + arr[j] == s时,有arr[i] + arr[j + 1] > s,则不需要对 j 以后的情况进行枚举。
  2. 对于某个arr[i], 可以找到一个确定的arr[j]当arr[i] + arr[j] == s时,有arr[i+1] + arr[j] > s,则不需要对 i 以后的情况进行枚举。

那么对于这个问题可以采用two pointers的思想。先让i = 0, j = n - 1,也就是i指针指向第一个元素,j指针指向最后一个元素。根据arr[i] + arr[j]和s的大小来决定i向右移还是j向左移,直到i >= j。

判断条件如下:
1)如果arr[i] + arr[j] == s,则输出结果。且由于序列递增,可以知道arr[i+1] + arr[j] > sarr[i] + arr[j-1] < sarr[i+1] + arr[j-1] 和s的大小关系不确定,所以等于s的结果只能是在[i+1, j-1]之间。
2)如果arr[i] + arr[j] < s,则有arr[i] + arr[j-1] < s ,但是arr[i+1] + arr[j]和s的大小关系不确定,则i向右移,i++。
3)如果arr[i] + arr[j] > s,则有arr[i+1] + arr[j] > s ,但是arr[i] + arr[j-1]和s的大小关系不确定,则j向左移,j–。
代码如下:

while(i < j)
{
	if(arr[i] + arr[j] == s)
	{
		cout<<"result = " << i << "+" << j <<endl;
	}
	else if(arr[i] + arr[j] < s)
	{
		i++;
	}
	else
	{
		j--;
	}
}

Easy+ 级例题:序列合并问题,将两个递增序列arr_1和arr_2合并为一个递增序列arr_3;
将i设置为arr_1序列的首元素,j设置为arr_2序列的首元素,然后通过比较大小来看那个该放入序列arr_3。
1)如果arr_1[i] > arr_2[j],说明现在arr_2[j]是当前最小的一个,放入arr_3中,然后j++。
2)如果arr_1[i] < arr_2[j],说明现在arr_1[i]是当前最小的一个,放入arr_3中,然后i++。
1)如果arr_1[i] == arr_2[j],则任选一个放入arr_3,然后把对应的pointer++。

//l1为数组arr_1的元素个数,l2为数组arr_2的元素个数
int mergeArray(const int arr_1[], const int arr_2[], int arr_3[], int l1, int l2)
{
	int i = 0, j = 0, index = 0;
	while(i < l1 && j < l2)
	{
		if(arr_1[i] >= arr_2[j]) {
			arr_3[index++] = arr_2[j++];
		}
		else {
			arr_3[index++] = arr_1[i++];
		}
	}
	//将剩余的全部加入到数组arr_3中
	while(i < l1) arr_3[index++] = arr_1[i++];
	while(j < l2) arr_3[index++] = arr_2[j++];
	
	return index;//返回arr_3数组元素个数
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值