在开始讲题目之前,要介绍一下这类题目的整体思路,双指针的题目和滑动窗口的题目很像,都是通过两个指针进行移动来解决问题,只不过滑动窗口是两个指针往同一个方向移动,而双指针是两个指针从左右两边往中间移动
双指针的很多题目都需要借助单调性来解决问题,单调性则是通过暴力解法推导出来的
1.移动零

2.复写零

3.快乐数

题目给的信息帮我们大大降低了题目的难度,这个数最后只有两种可能,无限循环不为1,或者最后是1

我们以19和2来分别画图分析
这是19的分析过程

这是2的分析过程,可以发现。到最后2成环了

这个图就有点像之前学过的链表成环问题了元素,当最后都是一时,相当于也是成了一个环,所以,这道题就相当于有两种成环的链表,一个环里的元素都是1,一个环里的元素不为1,所以,这个问题就转化成了,判断环里元素是不是1。
我们假设链表成环,那么我们一定可以用快慢指针来检验,并且快慢指针一定会在环中相遇
因此,只要来判断相遇时的元素是不是1就好了
接下来开始实现代码

4.盛最多容器的水
题目来源:11. 盛最多水的容器 - 力扣(LeetCode)

看题目可能不太好理解,看图就可以理解了,目的就是要装最多的水
我们可以用图来分析
最简单的方法就是暴力枚举,找到最大的容量,但时间复杂度可能会太大了,也可能会超时
我们需要来找一个更巧妙的方法
我们先定义一个max,来储存可能最大的值,如果新的容量大于max,就把max更新为新的容量
用两个指针来控制左右的区间,以开头为左区间,结尾为右区间
先固定一个边界,比如,先将左边界固定,那么右边界就是可以动的,在右边界向内缩小的过程中,宽度是一直在减小的,假如右边界的高度大于等于左边界,那么高度不变;假如右边界的高度小于左边界,高度减小,不管怎么说,容量都是在减小的。
所以说,更新的边界需要是较小的那一个,这样才能够给高度带来变化的可能性
当两个变价相遇时,循环就结束了
接下来,来实现一下

5.有效三角形的个数
题目来源:611. 有效三角形的个数 - 力扣(LeetCode)

一开始想到的方法肯定都是暴力枚举,写三层循环,来找可能的三角形个数,但这样效率太慢了
我们来用一种更巧妙的解法,双指针
在开始找个数之前,我们可以先用排序来优化一下效率
我们都知道,三角形可以成立的条件是任意两边之和大于第三边
那么,假如,我们可以直接看一下,较小的两个数之和是否大于第三个数,就可以只判断一次
并且,将数组先进行排序,就能够让我们使用接下来的一种方法
我们可以用双指针来完成这道题目,用一个数组来进行举例

先选取最大数为一条边,然后分别选取剩下的数中的最大数和最小数为right和left
假如left和right加起来大于max说明能组成三角形,并且因为数组是排好序的,所以left右边的数也一定能够和right和max组成三角形,因此,我们让right--;假如left和right加起来小于等于max,说明不能组成三角形,并且,如果right是右边的任何数,都不可能与left的和大于max,所以,我们需要让left++;
当right-left<1时循环停止,进行下一次循环,max这个下标的最小值是2.
接下来开始实现代码


6.查找总价格为目标值的两个商品
题目来源:LCR 179. 查找总价格为目标值的两个商品 - 力扣(LeetCode)

这道题的思路跟找有效三角形的个数那题类似,暴力解法肯定可以,但是可以利用单调性来降低复杂度
因为价格是排升序的,我们一开始定义两个指针,一个指向开头一个指向末尾,判断两数之和与目标值的关系
如果大于目标值,那么right--;
如果小于目标值,left++;
如果等于,跳出循环;
最后将下标为left和right的元素放进数组就好了

7.两数之和

这道两数之和跟后面的三数之和,四数之和有关系,可以说这题是那两题的基础
我们先用示例1来分析
设置两个指针从左右两边往中间走,当两个数之和大于目标值时,让右边那个指针--
当两个数之和小于目标值时,让左边那个指针++
一直找,最后就能够找到我们要的结果了


8.三数之和

三数之和的写法有借鉴前面的两数之和
先来分析一下题目,题目的要求是从容器中找到三个数之和等于0,我们可以换个思路来想,可以先固定一个数x,从剩下的数来找到和为-x的两个数
并且题目的要求是三元组不能重复,意味着不能有相同的三个数组成顺序不同的组
可以通过示例来观察

第一个和第二个结果都为0,但是只取其中一组
所以在完成该题的过程中,我们需要注意去重和边界问题


9.四数之和
四数之和的思路与三数之和基本类似,只不过外面多了一层循环
与三数之和相同,先对数组排序
我们以例1进行举例

我们需要找到四个数,使得这四个数之和等于目标值target
首先,我们将i固定在第一个位置,然后将j固定在i的下一个位置,然后让left在j的下一个位置,right在最后一个位置
一开始我需要找到四个数之和等于target,相当于target=numsi+numsj+numsleft+numsright
也就是说,我们要找到三个数的和等于target-numsi
继续往下推,就是要找到两个数之和等于numsleft+numsright
具体的思路与前面差不多,最重要的是,我们需要注意两个点和一种特殊情况
第一个点:越界,我们需要在每一个子循环检查是否越界
第二个点:去重,我们需要将重复的情况去除掉,因为我们是排好序的,所以这一点比较容易就可以做到了
特殊情况指的是假如数组的元素小于四,那么如果按照上述的思路就会导致越界,所以需要进行特殊的处理


以上就是本篇文章的全部内容了,如果对你有帮助,可以点个赞支持一下,感谢各位的观看
https://gitee.com/mo-ran-qingyun
这是我个人的gitee仓库,账号上文章的代码都会发到仓库里,有兴趣可以看一下