算法基础课学习笔记:(三)双指针Two Point

本文介绍了如何使用双指针优化算法解决寻找数组中两个数之和等于特定值的问题。从暴力遍历的O(n^2)复杂度出发,通过排序和双指针技巧降低到O(n log n)。详细阐述了优化过程,并给出了代码模板。最后提出了寻找三个数之和的思考题。
摘要由CSDN通过智能技术生成

算法基础课学习笔记:(三)双指针Two Point

       

算法介绍

       Two Point与其说是一种算法,更像是一种编程技巧,它并不需要复杂且严谨的数学证明,只是在编写程序的过程中顺手就优化了程序而已。
       

问题引入

       我们引入一个问题,给定一组全是正整数且没有重复数字的数列,和一个正整数 K K K,若数列中存在两个数处于不同位置的数 a a a b b b 使得 a + b = K a+b=K a+b=K,则将其视为一种方案,求数列中所有满足条件的方案数量。
       比方说,给定数列 [ 2 , 4 , 3 , 5 , 1 , 6 ] [2,4,3,5,1,6] [2,4,3,5,1,6] 和正整数 K = 8 K=8 K=8,则存在两个满足条件的方案: 2 + 6 = 8 2+6=8 2+6=8 3 + 5 = 8 3+5=8 3+5=8,最终答案输出2。
       
       我相信大部分人碰到这题的第一想法就是逐个扫描元素,找到每个元素对应的元素是否在序列中吧hh。
       来写一下暴力解法的代码:

int main(){
	int a[6]={2,4,3,5,1,6};
	int k=8;
	int ans=0;
	for(int i=0;i<6;i++){
		for(int j=0;j<6;j++{
			if(i!=j&&a[i]+a[j]==k) ans++;
		}
	}
	cout<<ans;
}

       分析一下暴力解法的时间复杂度,显然两重循环的时间复杂度是 o ( n 2 ) o(n^2) o(n2)的,对 n n n的数量在 1 0 5 10^5 105 级别是无法承受的。

暴力优化

       我们来看一下如何才能优化暴力解法。
       首先我们注意到,数组中没有重复数字,这就证明了每个元素 a a a 如果要满足条件,对应的元素 b b b 是唯一的,我们来将数组排个序。
       
       排序好之后的数组为 [ 1 , 2 , 3 , 4 , 5 , 6 ] [1,2,3,4,5,6] [1,2,3,4,5,6],我们借助两个指针变量 l e f t left left r i g h t right right,将 l e f t left left 指向数组开头, r i g h t right right 指向数组末尾,在这里插入图片描述
       我们可以将 l e f t left left r i g h t right right 指向的元素求和,显然和为 7 < K = 8 7<K=8 7<K=8,此时我们将 l e f t left left 右移到2,满足了 2 + 6 = K = 8 2+6=K=8 2+6=K=8,将方案数加1后同时将 l e f t left left 右移和 r i g h t right right 左移,循环操作直到 l e f t 和 r i g h t left和right leftright相遇。
       为什么能这么做呢,这是因为数组单调有序,只要移动指针,就能在只扫描数组一遍的情况下,完成方案统计。时间复杂度为 o ( n ) o(n) o(n)
       再加上我们排序的时间复杂度 o ( n l o g n ) o(nlogn) o(nlogn),总体时间复杂度就为 o ( n l o g n ) o(nlogn) o(nlogn)
       
       这种思想就被称作双指针,以一遍扫描数组的形式替代了扫描两个数组。
       
       这里给出代码模板

int main(){
	int a[6]={2,4,3,5,1,6};
	int k=8;
	int ans=0;
	sort(a,a+6);
	//此时数组内元素为[1,2,3,4,5,6]
	int left=0,right=5;
	while(left<right){
		if(a[left]+a[right]==k){
			ans++;
			left++,right--;
		}
		else if(a[left]+a[right]<k){
			left++;
		}
		else if(a[left]+a[right]>k){
			right--;
		}
	}
	cout<<ans;
}

       思考:如果找三个元素加一起等于 K K K的方案,该怎么改动?
       

总结

       双指针运算用于单调有序数组,将扫描两趟才能完成的事情降到扫描一趟就能完成。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值