【数据结构与算法】双指针算法

  我们还有更长的路要走,不过没关系,道路就是生活。 

前言 

  这是我自己刷算法题的第一篇博客总结。

  后期我会继续把刷算法题的笔记开源至博客上。

技巧 

1. 双指针算法,但实际上是利用数组下标来充当指针,并不是直接使用指针。

2. cur指针扫描遍历指针左边已经扫描遍历的部分,中间及右边还未扫描遍历的部分。

3. dest指针分隔指针左边已经排好的序的部分,中间及右边还未排序的部分

4. 划分为三个区间:[0,dest-1][dest,cur-1][cur,n-1]

5. 双指针算法分为两类:就地操作异地操作,可以先异地操作最后优化成就地操作

6. 就地操作不需要重新创建一个数组,但是需要考虑覆盖问题异地操作需要重新创建一个数组,但是不用考虑覆盖问题

7. 双指针算法可以从前到后遍历,又可以从后到前遍历

8. 双指针算法又可以变形为快慢指针,一个移动快的指针,一个移动慢的指针。

9. 双指针算法还可以变形为相撞指针,两个指针相向而行,最终走到一起,共同遍历数组相撞指针一般需要先排序,然后利用单调性,两个指针从两边向中间遍历

例题

1. leetcode-283题: 283. 移动零 - 力扣(LeetCode)https://leetcode.cn/problems/move-zeroes/

void moveZeroes(vector<int>& nums) 
{
     int cur=0,dest=0;
     while(cur<nums.size())
     {
         if(nums[cur]!=0)
         {
             swap(nums[cur],nums[dest]);
             cur++;
             dest++;
         }
         else
         {
              cur++;
         }
     }
}

2. leetcode-1089题:  1089. 复写零 - 力扣(LeetCode)https://leetcode.cn/problems/duplicate-zeros/

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

3. leetcode-208题: 

202. 快乐数 - 力扣(LeetCode)https://leetcode.cn/problems/happy-number/

class Solution 
{
public:
    int ADD(int n)
    {
        int sum=0;
        while(n>=10)
        {
            sum+=(n%10)*(n%10);
            n=n/10;
        }
        sum+=n*n;
        return sum;
    }
    bool isHappy(int n) 
    {
        int slow=n,fast=ADD(n);
        while(slow!=fast)
        {
            slow=ADD(slow);
            fast=ADD(fast);
            fast=ADD(fast);
        }
        if(fast==1)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
};

4. leetcode-11题:  

11. 盛最多水的容器 - 力扣(LeetCode)https://leetcode.cn/problems/container-with-most-water/submissions/606075497/

class Solution 
{
public:
    int Min(int x,int y)
    {
        return x<=y?x:y;
    }
    int Max(int x,int y)
    {
        return x>=y?x:y;
    }
    int maxArea(vector<int>& height) 
    {
        int s=0;
        int left=0,right=height.size()-1;
        while(left!=right)
        {
            s=Max((right-left)*Min(height[right],height[left]),s);
            if(height[left]<height[right])
            {
                left++;
            }
            else
            {
                right--;
            }
        }
        return s;
    }
};

5. leetcode-611题:  

611. 有效三角形的个数 - 力扣(LeetCode)https://leetcode.cn/problems/valid-triangle-number/

class Solution 
{
public:
    int triangleNumber(vector<int>& nums) 
    {
        int ret=0;
        sort(nums.begin(),nums.end());
        for(int last=nums.size()-1;last>1;last--)
        {
            int left=0,right=last-1;
            while(left<right)
            {
                 while(nums[right]+nums[right-1]>nums[last])
                {
                    if(nums[left]+nums[right]>nums[last])
                    {
                        ret=ret+(right-left);
                        break;
                    }
                    else
                    {
                        left++;
                    }
                }
                right--;
            }
        }
        return ret;
    }
};

6. leetcode-179题: 

LCR 179. 查找总价格为目标值的两个商品 - 力扣(LeetCode)https://leetcode.cn/problems/he-wei-sde-liang-ge-shu-zi-lcof/description/

class Solution {
public:
    vector<int> twoSum(vector<int>& price, int target) 
    {
        int left=0,right=price.size()-1;
        while(price[left]+price[right]!=target)
        {
            if(price[left]+price[right]<target)
            {
                left++;
            }
            else
            {
                right--;
            }
        }    
        vector<int> arr;
        arr.push_back(price[left]);
        arr.push_back(price[right]);
        return arr;
    }
};

7. leetcode-15题:  

15. 三数之和 - 力扣(LeetCode)https://leetcode.cn/problems/3sum/

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

8. leetcode-18题:  

18. 四数之和 - 力扣(LeetCode)https://leetcode.cn/problems/4sum/description/

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) 
    {
        sort(nums.begin(),nums.end());
        vector<vector<int>> set;
        if(nums.size()<4)
        {
            return set;
        }
        int first=0;
        while(first<nums.size()-3)
        {
            int second=first+1;
            while(second<nums.size()-2)
            {
                int left=second+1,right=nums.size()-1;
                long long tar=(long long)target-nums[first]-nums[second];
                while(left<right)
                {
                    if(nums[left]+nums[right]<tar)
                    {
                        left++;
                    }
                    else if(nums[left]+nums[right]>tar)
                    {
                        right--;
                    }
                    else
                    {
                        set.push_back({nums[first],nums[second],nums[left],nums[right]});
                        left++;
                        right--;
                        while(left<right&&nums[left]==nums[left-1])
                        {
                            left++;
                        }
                        while(left<right&&nums[right]==nums[right+1])
                        {
                            right--;
                        }
                    }
                }
                second++;
                while(second<nums.size()-2&&nums[second]==nums[second-1])
                {
                    second++;
                }
            }
            first++;
            while(first<nums.size()-3&&nums[first]==nums[first-1])
            {
                first++;
            }
        }
        return set;
    }
};

致谢

  感谢您花时间阅读这篇文章!如果您对本文有任何疑问、建议或是想要分享您的看法,请不要犹豫,在评论区留下您的宝贵意见。每一次互动都是我前进的动力,您的支持是我最大的鼓励。期待与您的交流,让我们共同成长,探索技术世界的无限可能!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值