算法综合篇专题一:双指针问题

"就算没有看清那株灿烂的花蕊,也应该放声歌颂赞美鲜红的玫瑰" 


1、移动零

(1) 题目解析        

(2) 算法原理      

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        for(int cur=0,dest=-1;cur<nums.size();++cur)
        {
            if(nums[cur]) swap(nums[cur],nums[++dest]);
        }
    }
};

2、复写零

(1) 题目解析        

(2) 算法原理                 

class Solution {
public:
    void duplicateZeros(vector<int>& arr) {
        // 1.找到最后一个下标位置
        int cur = 0;
        int dest = -1;
        int n = arr.size();
        while(dest < n)
        {
            if(arr[cur]) dest++;
            else dest += 2;
            // dest走到边界
            if(dest >= n-1) break;
            cur++;
        }

        // 处理边界存在最后一个数为0
        if(dest == n)
        {
            arr[n-1] = 0;
            cur--,dest-=2;
        }

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


3、快乐数 

(1) 题目解析

(2) 算法原理        

class Solution {
public:
    int bitSum(int n)
    {
        int sum = 0;
        while(n)
        {
            int a = n % 10;
            sum += pow(a,2);
            n /= 10;
        }
        return sum;
    }
    bool isHappy(int n) {
        // 快慢指针
        int slow = n,fast = bitSum(n);
        while(slow != fast)
        {
            slow = bitSum(slow);
            fast = bitSum(bitSum(fast));
        }

        return slow == 1 ? true : false;
    }
};

4、盛最多水的容器 

(1) 题目解析        

(2) 算法原理        

class Solution {
public:
    int maxArea(vector<int>& arr) {
        int n = arr.size();
        int left=0,right=n-1;
        int ret = 0;
        while(left < right)
        {
            int height = min(arr[right],arr[left]);
            int v = (right-left) * height;
            ret = max(ret,v);
            
            height == arr[right] ? right--:left++;
        } 
        return ret;
    }
};


5、有效三角)——形个数

(1) 题目解析        

(2) 算法原理        

class Solution {
public:
    int triangleNumber(vector<int>& nums) {
        int n = nums.size();
        sort(nums.begin(),nums.end());
        int num = 0;
        for(int c=nums.size()-1;c>=2;--c)
        {
            int left = 0;
            int right = c-1;
            while(left < right)
            {
                int sum = nums[left] + nums[right];
                if(sum > nums[c])
                {
                    num += (right-left);
                    right--;
                }
                else left++;
            }
        }

        return num;
    }
};

6、和为s的两个数

(1) 题目解析

(2) 算法原理

        

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

        return {-1};
    }
};

   


7、三数之和

(1) 题目解析        

(2) 算法原理

        

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        int n = nums.size();
        vector<vector<int>> res;
        sort(nums.begin(),nums.end());
        for(int i=0;i<n;)
        {
            if(nums[i] > 0) break;
            int left = i+1,right = n-1;
            while(left < right)
            {
                int tar = -nums[i];
                int sum = nums[left] + nums[right];
                if(sum > tar) right--;
                else if(sum < tar) left++;
                else
                {
                    res.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 < n && nums[i] == nums[i-1]) i++;
        }
        return res;
    }
};


8、四数之和

(1) 题目解析

        这道题的本质和三数之和没什么区别,只不过比三数字和多套一层循环就能够解决了。所以不再细讲,注意到各个循环内的越界去重问题就行。

(2) 算法原理     

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        int n = nums.size();
        // 排序
        sort(nums.begin(),nums.end());
        vector<vector<int>> res;
        for(int i=0;i<n;)
        {
            for(int j=i+1;j<n;)
            {
                int left =j+1,right=n-1;
                while(left < right)
                {
                    // 固定两个数
                    // 可能出现溢出情况
                    long long tar = (long long)target - nums[i] - nums[j];
                    int sum = nums[left] + nums[right];
                    if(sum > tar) right--;
                    else if(sum < tar) left++;
                    else 
                    {
                        res.push_back({nums[i],nums[j],nums[left],nums[right]});
                        left++,right--;

                        while(left < right && nums[left] == nums[left-1]) left++;
                        while(left < right && nums[right] == nums[right+1]) right--;
                    }
                }

                j++;
                while(j < n && nums[j] == nums[j-1]) j++;
            }
            i++;
            while(i < n && nums[i] == nums[i-1]) i++;
        }

        return res;
    }
};


本篇到此结束,感谢你的阅读。

祝你好运,向阳而生~


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值