【 刷题 】双指针

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);
    }
相关推荐
猿人谷4 分钟前
Surrogate Model:让进化算法学会“预测”,为什么它正在成为智能优化的重要技术?
后端·算法·架构
青少儿编程课堂2 小时前
蓝桥杯青少组图形化 STEMA 省考(报名倒计时·11/22开考)+ 全国青少年信息素养大赛 2026—2027赛季 + 电子学会图形化考级:校园华容道大闯关
c++·python·算法·bfs·信息学竞赛
在猴站学算法3 小时前
(《统计学习方法》(第2版) 李航)第2章 感知机算法
学习·算法·机器学习·统计学习
Rainmicro3 小时前
【无标题】
java·数据库·算法
NEFU_Jyj13 小时前
牛客周赛R168
算法
Navigator_Z20 小时前
LeetCode //C - 1317. Convert Integer to the Sum of Two No-Zero Integers
c语言·算法·leetcode
D e re k ZH21 小时前
C++ 标准库算法全景指南
数据结构·c++·算法
冻柠檬飞冰走茶1 天前
字母移动游戏题解:贪心求最长可保留连续子串(附 C 实现)
c语言·开发语言·数据结构·算法·动态规划