算法模板 双指针法

双指针法:用两个指针一个循环来完成(有时候两个循环才能完成的)一件事情

反转链表(一指针在前,一指针在后)
https://leetcode-cn.com/problems/reverse-linked-list/submissions/

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* pre=NULL,*cur=head;
        while(cur!=NULL)
        {
            ListNode* temp=cur->next;
            cur->next=pre;
            pre=cur;
            cur=temp;
        }
        return pre;
    }
};

反转字符串(数组最前一个指针,最后一个指针,两个指针最后汇聚在一起)
https://leetcode-cn.com/problems/reverse-string/submissions/

class Solution {
public:
    void swap(char& a,char& b)
    {
        char temp=a;
        a=b;
        b=temp;
    }
    void reverseString(vector<char>& s) {
            if(s.size()==1) return;
            for(int i=0,j=s.size()-1;i<=(s.size()-2)/2;i++,j--)
            {
                swap(s[i],s[j]);
            }
    }
};

移除元素(一个快指针用于筛选出想要的元素,一个慢指针用于保存答案)
https://leetcode-cn.com/problems/remove-element/submissions/

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int slow=0;
        for(int fast=0;fast<nums.size();fast++)
        {
            if(nums[fast]==val) continue;
            else
            {
                nums[slow]=nums[fast];
                slow++;
            }
        }
        return slow;
    }
};

注意C语言的逻辑运算符(&& ||)是从左到右运算的

删除有序数组中的重复项(一个快指针用于筛选出想要的元素,一个慢指针用于保存答案)
https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        if(nums.size()==0) return 0;
        
        int slow=0;
        for(int fast=0;fast<nums.size();fast++)
        {
            if(nums[fast]==nums[slow]) continue;
            else
            {
                nums[++slow]=nums[fast];
            }
        }
        return slow+1;
    }
};

移动零(一个快指针用于筛选出想要的元素,一个慢指针用于保存答案)
https://leetcode-cn.com/problems/move-zeroes/

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int slow=0;
        for(int fast=0;fast<nums.size();fast++)
        {
            if(nums[fast]==0) continue;
            else
            {
                nums[slow]=nums[fast];
                slow++;
            }
        }
        while(slow<nums.size())
        {
            nums[slow]=0;
            slow++;
        }
    }
};

比较含退格的字符串(一个快指针用于筛选出想要的元素,一个慢指针用于保存答案)
https://leetcode-cn.com/problems/backspace-string-compare/submissions/

class Solution {
public:
    bool backspaceCompare(string s, string t) {
        if(dealStr(s)==dealStr(t)) return true;
        else return false;

    }

    string dealStr(string str)
    {
        string ans;
        int slow=0;
        for(int fast=0;fast<str.size();fast++)
        {
            if(str[fast]!='#')            //增加一个字符
            {
                str[slow]=str[fast];
                slow++;
            }
            else
            {
                if(slow>0) slow--;      //减少一个字符
            }
        }
        for(int i=0;i<slow;i++)
        {
            ans+=str[i];
        }
        return ans;
    }
};

有序数组的平方(数组最前一个指针,最后一个指针,两个指针最后汇聚在一起)
https://leetcode-cn.com/problems/squares-of-a-sorted-array/

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {

        vector<int> ans(nums.size());       //默认值为0
        for(int i=0,j=nums.size()-1,pos=nums.size()-1;i<=j;)
        {
            if(nums[i]*nums[i]>=nums[j]*nums[j])
            {
                ans[pos--]=nums[i]*nums[i];
                i++;
            }
            else
            {
                ans[pos--]=nums[j]*nums[j];
                j--;
            }
        }
        return ans;    
    }
};

滑动窗口法:在题目中有连续的子序列这一描述时,可以考虑使用

长度最小的子数组(滑动窗口法,也是快慢指针法中的一类)
https://leetcode-cn.com/problems/minimum-size-subarray-sum/

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int slow=0,result=INT32_MAX,sum=0;      //sum用于记录当前序列的和
        for(int fast=0;fast<nums.size();fast++)
        {
            sum+=nums[fast];
            while(sum>=target)          //当前序列符合要求
            {
                //更新答案
                int len=fast-slow+1;    //当前符合要求的序列的长度
                if(result>len) result=len;

                //滑动窗口向前缩小
                sum-=nums[slow];
                slow++;
            }
        }
        if(result==INT32_MAX) return 0;
        else return result;
    }
};

水果成篮(滑动窗口法,也是快慢指针法中的一类)
https://leetcode-cn.com/problems/fruit-into-baskets/

class Solution {
public:
    int totalFruit(vector<int>& fruits) {
        map<int,int> dict;      //记录现在共有多少水果类型,每个类型有多少颗
        int slow=0,result=0;
        for(int fast=0;fast<fruits.size();fast++)
        {
            //当前水果种类数<2,往dict里面新加水果
            if(dict.size()<2)
            {
                //是新的一类水果
                if(!dict.count(fruits[fast]))
                {
                    dict[fruits[fast]]=1;
                }
                else
                {
                    dict[fruits[fast]]++;
                }
                //当前子序列长度
                int len=fast-slow+1;
                //更新答案
                result=result<len?len:result;
            }
            //dict已满,但是里面已有同类型的水果
            else if(dict.size()==2&&dict.count(fruits[fast]))
            {
                dict[fruits[fast]]++;
                //当前子序列长度
                int len=fast-slow+1;
                //更新答案
                result=result<len?len:result;
            }
            //dict已满,开始缩小窗口
            else
            {
                while(dict.size()==2)
                {
                    //窗口向前移动
                    dict[fruits[slow]]--;
                    //若该种果实数目为0,则从dict中删除
                    if(dict[fruits[slow]]==0)
                    {
                        dict.erase(fruits[slow]);
                    }
                    slow++;
                }
                //fast指针不动
                fast-=1;
            }
        }
        return result;
    }
};

三数之和(排序+双指针)
https://leetcode-cn.com/problems/3sum/

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> ans;
        sort(nums.begin(),nums.end());
        for(int i=0;i<nums.size();i++)
        {
            if(i==0||nums[i]!=nums[i-1])
            {
                int left=i+1,right=nums.size()-1;
                while(left<right)
                {
                    if(nums[i]+nums[left]+nums[right]<0)
                    {
                        while(left<right&&nums[left+1]==nums[left]) left++;
                        left++;
                    }
                    else if(nums[i]+nums[left]+nums[right]>0)
                    {
                        while(left<right&&nums[right-1]==nums[right]) right--;
                        right--;
                    }
                    else
                    {
                        ans.push_back({nums[i],nums[left],nums[right]});
                        //去重
                        while(left<right&&nums[left+1]==nums[left]) left++;
                        while(left<right&&nums[right-1]==nums[right]) right--;
                        left++;
                        right--;
                    }
                }
            }
        }
        return ans;
    }
};

四数之和
https://leetcode-cn.com/problems/4sum/

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector<vector<int>> ans;
        sort(nums.begin(),nums.end());
        for(int i=0;i<nums.size();i++)
        {
            if(i==0||nums[i]!=nums[i-1])
            {
                for(int j=i+1;j<nums.size();j++)
                {
                    if(j==i+1||nums[j]!=nums[j-1])
                    {
                        int left=j+1,right=nums.size()-1;
                        while(left<right)
                        {
                            long long a=nums[i],b=nums[j],
                            c=nums[left],d=nums[right],mytarget=target;
                            if(a+b+c+d<mytarget)
                            {
                                while(left<right&&nums[left+1]==nums[left]) left++;
                                left++;
                            }
                            else if(a+b+c+d>mytarget)
                            {
                                while(left<right&&nums[right-1]==nums[right]) right-- ;
                                right--;
                            }
                            else
                            {
                                ans.push_back({nums[i],nums[j],nums[left],nums[right]});
                                while(left<right&&nums[left+1]==nums[left]) left++;
                                left++;
                                while(left<right&&nums[right-1]==nums[right]) right-- ;
                                right--;
                            }
                        }
                    }
                }
            }
        }
        return ans;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值