双指针算法
常见的双指针算法由两种形式,一种是对撞指针,一种是快慢指针
对撞指针:一般用于顺序结构中,也称左右指针。
从两端向中间移动,一个指针从最左端开始,一个指针从最右端开始,然后逐渐往中间
逼近,直到两个指针相遇或者错开。
快慢指针:又称为龟兔赛跑算法,在学习链表的时候我们就用到过双指针,例如:一个指针一次走
一步,另一个指针一次走两步,一般用于处理环形链表或者数组等问题。
具体题目
1.移动零

解决方法:双指针

java
public void moveZeroes(int[] nums) {
int cur=0;
int dest=-1;
int n=nums.length;
while (cur<n){
if (nums[cur]==0){
cur++;
}else{
dest++;
swap(nums,dest,cur);
cur++;
}
}
}
private void swap(int[] nums, int dest, int cur) {
int temp=nums[dest];
nums[dest]=nums[cur];
nums[cur]=temp;
}
2.复写零
解决方法:双指针

java
public void duplicateZeros(int[] arr) {
//首先要先找到要复写的位置
//然后进行复写
int cur=0;
int dest=-1;
int n=arr.length;
while (cur<n){
if (arr[cur]==0){
dest+=2;
}else{
dest++;
}
if (dest<n-1){
cur++;
}else{
break;
}
}
//通过上面的代码,cur所对应在数组中的位置就是最后一个要复写的位置,然后进行复写
//首先先判断下数组是否越界
if(dest>=n){
arr[n-1]=0;
dest-=2;
cur--;
}
while (cur>=0){
if (arr[cur]==0){
arr[dest--]=0;
arr[dest--]=0;
}else{
arr[dest]=arr[cur];
dest--;
}
cur--;
}
}
3.快乐数


所以这个题,直接用快慢指针就可以解决该问题,这两个指针一定会相遇,就看相遇点是不是1,如果是1,则返回true,否则返回false
java
public boolean isHappy(int n) {
int left=n;
int right=bitSum(n);
while (left!=right){
left=bitSum(left);
right=bitSum(bitSum(right));
}
return left==1;
}
private int bitSum(int n) {
int sum=0;
while (n!=0){
int number=n%10;
sum+=(number*number);
n/=10;
}
return sum;
}
4.盛最多水的容器


这个题的思路就是:利用单调性,使用双指针来解决问题
只需要算min(左边界值,右边界值)*宽度即可,不需要算min(边界值,中间值)*宽度,因为,中间值对于边界值看来说,宽度肯定是减小的,高度可能减小,可能不变,所以体积是一定会减小的,所以只需要算边界值即可,然后算出来后,保存下来体积,同时让高度低的边界值移动即可,如果左边界值小于右边界值,则left++,否则right--
java
public int maxArea(int[] height) {
int max=-1;
int left=0;
int right=height.length-1;
while (left<right){
int v=Math.min(height[left],height[right])*(right-left);
max=Math.max(max,v);
if (height[left]<height[right]){
left++;
}else{
right--;
}
}
return max;
}
5.有效三角形的个数


java
public int triangleNumber(int[] nums) {
Arrays.sort(nums);
int ret=0; //记录三角形的个数
int A=nums.length-1;// 先固定一个数
while (A>=2){ //如果A小于2,那么双指针则无法进行定位
int left=0;
int right=A-1;
while (left<right){
if (nums[left]+nums[right]>nums[A]){
ret+=(right-left);
right--;
}else{
left++;
}
}
A--;
}
return ret;
}
6.和为S的两个数
LCR 179. 查找总价格为目标值的两个商品 - 力扣(LeetCode)


java
public int[] twoSum(int[] price, int target) {
int[] ret=new int[2];
int left=0;
int right=price.length-1;
while (left<right){
if (price[left]+price[right]>target){
right--;
}else if (price[left]+price[right]<target){
left++;
}else {
ret[0]=price[left];
ret[1]=price[right];
return ret;
}
}
return ret;
}
7.三数之和


java
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> list=new ArrayList<>();
int A=0; //首先,先固定一个数
while (A<nums.length){
int left=A+1;
int right=nums.length-1;
int aim=-nums[A]; //表示nums[A]的相反数,只要nums[left]+nums[right]=-num[A],那么他们三个相加就等于0
while (left<right){
int sum=nums[left]+nums[right];
if (sum<aim){
left++;
}else if (sum>aim){
right--;
}else{
//说明找到目标值了
List<Integer> integerList=new ArrayList<>();
integerList.add(nums[A]);
integerList.add(nums[left]);
integerList.add(nums[right]);
list.add(integerList);
//不漏
left++;
right--;
//去重,同时避免数组越界
while (left<right&&nums[left]==nums[left-1]){
left++;
}
while (left<right&&nums[right]==nums[right+1]){
right--;
}
}
}
A++;
//同样要去重和避免数组越界
while (A<nums.length&&nums[A]==nums[A-1]){
A++;
}
}
return list;
}
8.四数之和


java
public List<List<Integer>> fourSum(int[] nums, int target) {
Arrays.sort(nums);
List<List<Integer>> list=new ArrayList<>();
int A=0;
while (A<nums.length){
int B=A+1;
while (B<nums.length){
int left=B+1;
int right=nums.length-1;
long aim=(long)target-nums[A]-nums[B]; //改成long类型因为避免超过int的最大限制
while (left<right){
if (nums[left]+nums[right]>aim){
right--;
}else if (nums[left]+nums[right]<aim){
left++;
}else{
//找到目标值了
List<Integer> integerList=new ArrayList<>();
integerList.add(nums[A]);
integerList.add(nums[B]);
integerList.add(nums[left]);
integerList.add(nums[right]);
list.add(integerList);
//不漏
left++;
right--;
//去重同时避免数组越界
while (left<right&&nums[left]==nums[left-1]){
left++;
}
while (left<right&&nums[right]==nums[right+1]){
right--;
}
}
}
B++;
while (B<nums.length&&nums[B]==nums[B-1]){
B++;
}
}
A++;
while (A<nums.length&&nums[A]==nums[A-1]){
A++;
}
}
return list;
}
