算法题目---双指针算法

双指针算法

常见的双指针算法由两种形式,一种是对撞指针,一种是快慢指针

对撞指针:一般用于顺序结构中,也称左右指针。

从两端向中间移动,一个指针从最左端开始,一个指针从最右端开始,然后逐渐往中间

逼近,直到两个指针相遇或者错开。

快慢指针:又称为龟兔赛跑算法,在学习链表的时候我们就用到过双指针,例如:一个指针一次走

一步,另一个指针一次走两步,一般用于处理环形链表或者数组等问题。

具体题目

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.复写零

1089. 复写零 - 力扣(LeetCode)

解决方法:双指针

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.快乐数

202. 快乐数 - 力扣(LeetCode)

所以这个题,直接用快慢指针就可以解决该问题,这两个指针一定会相遇,就看相遇点是不是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.盛最多水的容器

11. 盛最多水的容器 - 力扣(LeetCode)

这个题的思路就是:利用单调性,使用双指针来解决问题

只需要算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.有效三角形的个数

611. 有效三角形的个数 - 力扣(LeetCode)

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.三数之和

15. 三数之和 - 力扣(LeetCode)

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.四数之和

18. 四数之和 - 力扣(LeetCode)

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;
    }
相关推荐
sin_hielo2 小时前
leetcode 3637
数据结构·算法·leetcode
2401_841495642 小时前
【LeetCode刷题】翻转二叉树
python·算法·leetcode··递归·节点·翻转二叉树
嵌入小生0072 小时前
数据结构与算法 | 完全二叉树的实现、哈希表的实现
linux·c语言·数据结构·算法·vim·嵌入式
渡我白衣2 小时前
无中生有——无监督学习的原理、算法与结构发现
人工智能·深度学习·神经网络·学习·算法·机器学习·语音识别
.小墨迹2 小时前
apollo中速度规划的s-t图讲解【针对借道超车的问题】
开发语言·数据结构·c++·人工智能·学习
小龙报2 小时前
【数据结构与算法】单链表的综合运用:1.合并两个有序链表 2.分割链表 3.环形链表的约瑟夫问题
c语言·开发语言·数据结构·c++·算法·leetcode·链表
蓝海星梦2 小时前
GRPO 算法演进:2025 年 RL4LLM 领域 40+ 项改进工作全景解析
论文阅读·人工智能·深度学习·算法·自然语言处理·强化学习
拼好饭和她皆失2 小时前
图论:最小生成树,二分图详细模板及讲解
c++·算法·图论
傻小胖2 小时前
19.ETH-挖矿算法-北大肖臻老师客堂笔记
笔记·算法·区块链