算法-双指针

目录

1、双指针遍历分割:避免开空间,原地处理

2、快慢指针:循环条件下的判断

3、左右指针(对撞指针):分析具有单调性,避免重复计算

双指针又分为双指针遍历分割,快慢指针和左右指针

1、双指针遍历分割:避免开空间,原地处理

(概念)核心思想:将数组分为两端、已处理的的部分,未处理的部分,cur遍历数组,指向未完成的数组,同时处理数组元素。dest指向处理完成的部分。

算法实际操作:cur指向第一个待处理的元素。dest指向处理完元素存放的位置,根据 cur指向数据的类型,进行不同操作。

例题:移动零

1089. 复写零 - 力扣(LeetCode)

cpp 复制代码
class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int n=nums.size();
        for(int cur=0,dest=-1;cur<nums.size();){
            if(nums[cur]){//非0的顺序不变,那么按序处理非0
                swap(nums[cur],nums[++dest]);
            }
            cur++;
        }
    }
};
cpp 复制代码
class Solution {
public:
    void duplicateZeros(vector<int>& arr) {
        int cur=0,dest=-1,n=arr.size();
        while(cur<n){
            if(arr[cur]) dest++;
            else dest+=2;
            if(dest>=n-1) break;
            cur++;
        }

        if(dest==n){
            arr[n-1]=0;
            dest=n-2;cur--;
        }
        while(cur>=0){
            if(arr[cur]) arr[dest--]=arr[cur--];
            else{
                arr[dest--]=0;
                arr[dest--]=0;
                cur--;
            }
        }
    }
};

2、快慢指针:循环条件下的判断

核心思想:经过分析,对于存在循环情况的问题,我们可以设置快慢指针来处理

.快乐数ss

cpp 复制代码
class Solution {
public:
    int bitsum(int n){
        int sum=0;
        while(n){
            int i=n%10;
            n/=10;
            sum+=i*i;
        }
        return sum;
    }

//快慢指针,不论是否是快乐数,都会进入循环,要不循环1为快乐数,要不是一堆数依次循环
    bool isHappy(int n) {
        int slow=n,fast=bitsum(n);
        while(slow!=1){
            slow=bitsum(slow);
            fast=bitsum(bitsum(fast));
            if(slow==fast&&slow!=1)
            return false;
        }
        return true;

    }
};

快乐数:分析可知必存在循环,分为1循环和多个数循环,然后利用快慢指针在循环中的前进速率不同,若相遇,判断循环数为多少,即可判断是否是快乐数

3、左右指针(对撞指针):分析具有单调性,避免重复计算

核心思想:在暴击解法上,利用单调性,避免重复计算,

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

cpp 复制代码
class Solution {
public:
    int maxArea(vector<int>& height) {
        int n=height.size();
        int left=0,right=n-1;
        int ret=(right-left)*min(height[left],height[right]);//记录最大值
        while(left<right){
            if(height[left]<=height[right]){
                left++;
            }else{
                right--;
            }
            ret=max(ret,(right-left)*min(height[left],height[right]));
        }
        return ret;
    }
};

实现操作:定义左右指针,left=0,right=n-1,ret=H*W,left和right向中间靠近的话,w一定减小,h只有增大才能实现ret变大。

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

cpp 复制代码
class Solution {
public:
    void duplicateZeros(vector<int>& arr) {
        int cur=0,dest=-1,n=arr.size();
        while(cur<n){
            if(arr[cur]) dest++;
            else dest+=2;
            if(dest>=n-1) break;
            cur++;
        }

        if(dest==n){
            arr[n-1]=0;
            dest=n-2;cur--;
        }
        while(cur>=0){
            if(arr[cur]) arr[dest--]=arr[cur--];
            else{
                arr[dest--]=0;
                arr[dest--]=0;
                cur--;
            }
        }
    }
};

暴力枚举三层循环

简化:排序后,固定两个值------三角形中较大的那两个,然后移动较小的那个值,变成求在某一有序区间内大于某值的个数。(利用单调性)

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

cpp 复制代码
class Solution {
public:
    vector<int> twoSum(vector<int>& price, int target) {
        int n=price.size();
        int low=0,height=n-1;
        while(low<height){
            if(price[low]+price[height]<target){
                low++;
            }else if(price[low]+price[height]>target){
                height--;
            }
            else{
                break;
            }
        }
        return {price[low],price[height]};
    }
};

暴力枚举+利用单调性优化:类盛水容器

cpp 复制代码
class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        int n=nums.size();
        vector<vector<int>> ret;

        for(int k=0;k<n-2;){
            int left=k+1,right=n-1;
            int target=-nums[k];
            while(left<right){
                if(nums[left]+nums[right]<target){
                    left++;
                }else if(nums[left]+nums[right]>target){
                    right--;
                }
                else{
                    ret.push_back(vector<int>{nums[k],nums[left],nums[right]});
                    left++;right--;
                    while(left<right&&nums[left]==nums[left-1])left++;//细节问题:不重复同时判断不越界:left<right
                    while(left<right&&nums[right]==nums[right+1])right--;
                }
            }
            k++;
            while(k<n-2&&nums[k]==nums[k-1])k++;
        }
        return ret;
    }
};

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

类上,对内两层的暴力改为求目标值

cpp 复制代码
class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        int n=nums.size();
        sort(nums.begin(),nums.end());
        vector<vector<int>> ret;

        for(int x=0;x<n-3;){//固定第一个数
            for(int k=x+1;k<n-2;){//固定第二个数
                long long targeti=(long long)target-(nums[x]+nums[k]);
                for(int left=k+1,right=n-1;left<right;){
                    long long sum=nums[left]+nums[right];
                    if(sum>targeti){
                        right--;
                    }else if( targeti>sum){
                        left++;
                    }else{
                        
                        ret.push_back(vector<int>{nums[x],nums[k],nums[left],nums[right]});
                        left++;
                        right--;
                        while(left<right&&nums[left]==nums[left-1]) left++;//注意仅仅,找到target去重,未找到的话,前面那个值未被统计不同去重
                        while(left<right&&nums[right]==nums[right+1]) right--;
                    }
                   
                }
            k++;
            while(k<n-2&&nums[k]==nums[k-1]) k++;
            }
        x++;
        while(x<n-3&&nums[x]==nums[x-1]) x++;
        }
        return ret;
    }
};
相关推荐
pianmian14 小时前
python数据结构基础(7)
数据结构·算法
好奇龙猫6 小时前
【学习AI-相关路程-mnist手写数字分类-win-硬件:windows-自我学习AI-实验步骤-全连接神经网络(BPnetwork)-操作流程(3) 】
人工智能·算法
sp_fyf_20246 小时前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-11-01
人工智能·深度学习·神经网络·算法·机器学习·语言模型·数据挖掘
ChoSeitaku7 小时前
链表交集相关算法题|AB链表公共元素生成链表C|AB链表交集存放于A|连续子序列|相交链表求交点位置(C)
数据结构·考研·链表
偷心编程7 小时前
双向链表专题
数据结构
香菜大丸7 小时前
链表的归并排序
数据结构·算法·链表
jrrz08287 小时前
LeetCode 热题100(七)【链表】(1)
数据结构·c++·算法·leetcode·链表
oliveira-time7 小时前
golang学习2
算法
@小博的博客7 小时前
C++初阶学习第十弹——深入讲解vector的迭代器失效
数据结构·c++·学习
南宫生8 小时前
贪心算法习题其四【力扣】【算法学习day.21】
学习·算法·leetcode·链表·贪心算法