【 刷题 】双指针

1.双指针

283. 移动零 - 力扣(LeetCode)

采用数组分块的思想

bash 复制代码
void moveZeroes(vector<int>& nums) {
        for(int cur=0,dst=-1;cur<nums.size();cur++)
        {
            //[0,dst]非0,[dst+1,cur-1]为0
            
            if(nums[cur]) swap(nums[++dst],nums[cur]);

        }

    }

1089. 复写零 - 力扣(LeetCode)

分析题目:由前向后会导致数据覆盖,因此采用由后向前,需要先找到最后一个数字,处理特殊情况,然后进行覆写

bash 复制代码
void duplicateZeros(vector<int>& arr) {
        //1.找到最后一个位置
        int cur=0,dst=-1;
        while(cur<arr.size())
        {
            if(arr[cur]==0) dst+=2;
            else dst++;
            if(dst>=arr.size()-1) break;
            cur++;
        }
        
        //2.进行覆写
        //判断dst是否越界,进行越界处理
        if(dst==arr.size())
        {
            arr[dst-1]=0;
            dst-=2;
            cur--;
        }
        //开始覆写
        while(cur>=0)
        {
            if(arr[cur]==0)
            {
                arr[dst--]=0;
                arr[dst--]=0;
                cur--;
            }
            else
            {
                arr[dst--]=arr[cur--];
            }
            
        }
        

    }

202. 快乐数 - 力扣(LeetCode)

很显然这题是用快慢指针,很常规

bash 复制代码
int SumSqueue(int m)
    {
        int sum=0;
        while(m)
        {
            sum+=pow(m%10,2);
            m/=10;
        }
        return sum;
    }
    bool isHappy(int n) {
        int fast=SumSqueue(n);
        int slow=n;
        while(slow!=fast)
        {
            fast=SumSqueue(SumSqueue(fast));
            slow=SumSqueue(slow);
        }
        if(fast==1) return true;
        else return false;
    }

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

本题使用对撞指针来解,分情况讨论,每次都选择可能比上一次体积更大的情况

bash 复制代码
int maxArea(vector<int>& height) {
        int left=0,right=height.size()-1,ret=0;
        while(left<right)
        {
            int v=min(height[right],height[left])*(right-left);
            ret=max(ret,v);
            if(height[left]<height[right]) left++;
            else right--;
            
        }
        return ret;

    }

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

满足两边之和大于最长边即可组成三角形,我们可以将数组排序,三层遍历暴力求解会超时,进行优化。控制最长边,在左区间进行取舍

bash 复制代码
int triangleNumber(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        int ret=0,n=nums.size();
        for(int i=2;i<n;i++)//固定最大的边
        {
            int left=0,right=i-1;
            while(left<right)//对撞剩余两条边
            {
                if(nums[left]+nums[right]>nums[i])
                {
                    ret+=right-left;
                    right--;
                }
                else
                {
                    left++;
                }

            }
        }
        return ret;

    }

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

固定一个数,其余两数相加之和等于这个数的相反数即可,注意跳过重复的元素

bash 复制代码
vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> res;
        sort(nums.begin(),nums.end());
        for(int i=nums.size()-1;i>1;i--)
        {
            int j=0,k=i-1;
            int ret=-nums[i];
            while(j<k)
            {
                if(nums[j]+nums[k]==ret)
                {
                    res.push_back({nums[i],nums[j],nums[k]});
                    j++,k--;
                    while(j<k&&nums[j]==nums[j-1]) j++;
                    while(j<k&&nums[k]==nums[k+1]) k--;
                }
                else if(nums[j]+nums[k]<ret) j++;
                else k--;
            }
            while(i>1&&nums[i]==nums[i-1]) i--;
            
        }
        return res;
    }

2. 滑动窗口

滑动窗口本质还是双指针,只不过换了一种用法,我们之前做过对撞指针,快慢指针和分区指针这个也是类似的用法,

209. 长度最小的子数组 - 力扣(LeetCode)

解题时注意符合要求时更新结果,如果不满足条件就滑动左边窗口

复制代码
int minSubArrayLen(int target, vector<int>& nums) {
        int n=nums.size();
        int left=0,right=0,ret=INT_MAX;
        int sum=0;
        while(right<n)
        {
            sum+=nums[right];
            while(sum>=target)
            {
                ret=min(ret,right-left+1);
                sum-=nums[left++];
            }
            right++;
        }
        return ret==INT_MAX?0:ret;
    }

438. 找到字符串中所有字母异位词 - 力扣(LeetCode)

这个要固定窗口的长度,定义两个哈希表来存储s字符串和p字符串的信息,用count计数来判断是否满足子串的条件,进窗口维护count,出窗口维护count

复制代码
vector<int> findAnagrams(string s, string p) {
        int hash2[128]={0},hash1[128]={0};
        for(auto e:p) hash2[e-'a']++;
        int m=p.size();
        int n=s.size();
        int left=0,right=0,count=0;
        vector<int>ret;
        while(right<n)
        {
            char out=s[right];
            hash1[out-'a']++;
            if(hash1[out-'a']<=hash2[out-'a']) count++;
            while(right-left+1>m)
            {
                if(hash1[s[left]-'a']<=hash2[s[left]-'a']) count--;
                hash1[s[left++]-'a']--;
            }
            if(count==m) ret.push_back(left);
            right++;
        }
        return ret;
    }

76. 最小覆盖子串 - 力扣(LeetCode)

这题和字母异位词类似,不同点是窗口不是固定的,而是滑动的,满足条件时更新chuangko

复制代码
int hash1[128]={0};int hash2[128]={0};
        int left=0,right=0,len=INT_MAX,retlen=-1,count=0;
        for(auto e:t) hash2[e]++;
        while(right<s.size())
        {
            char in=s[right];
            hash1[in]++;
            if(hash1[in]<=hash2[in]) count++;
            while(count==t.size())
            {
                if(right-left+1<len)
                {
                    retlen=left;
                    len=right-left+1;
                }
                char out=s[left++];
                if(hash1[out]<=hash2[out]) count--;
                hash1[out]--;
            }
            right++;
        }
        if(len==INT_MAX) return "";
        else return s.substr(retlen,len);
    }
相关推荐
啥都想学点的研究生1 小时前
一篇文章讲清楚:K-Means聚类算法
算法·kmeans·聚类
白狐_7981 小时前
408 数据结构|KMP做题方法:next、nextval和高频易错点
数据结构·算法
月华路1 小时前
《模型不玄学》第20章 两种评估视角
人工智能·算法·机器学习
禹凕2 小时前
快速幂算法详解与实战
python·算法
xxwl5852 小时前
高斯消元法异或版
人工智能·算法·机器学习
sylviiiiiia2 小时前
leetcode hot 100
python·算法·leetcode
OPEN-F2 小时前
ROS2系列教程:Gazebo插件(关节控制/IMU/激光雷达)
c++·python·数码相机·算法·机器人
luj_17682 小时前
虚实交融中的真实人物塑造
c语言·开发语言·网络·经验分享·算法
haolin123.3 小时前
STL vector底层揭秘:从构造到迭代器失效
开发语言·c++·算法