【算法从零到千】【1-7】 双指针算法


C++ 双指针算法(超通俗讲解 + 实战代码)

1. 移动零

283. 移动零https://leetcode.cn/problems/move-zeroes/

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

cpp 复制代码
class Solution {
public:
    void moveZeroes(vector<int>& nums) {
       int cur=0,curf=0;
       while(cur!=nums.size())
       {
            if(nums[cur]==0)
            {
                cur++;
            }
            else
            {
                swap(nums[curf],nums[cur]);
                curf++;
                cur++;
            }
            
       }
    }
};

2. 复写零

1089. 复写零https://leetcode.cn/problems/duplicate-zeros/

给你一个长度固定的整数数组 arr ,请你将该数组中出现的每个零都复写一遍,并将其余的元素向右平移。

注意:请不要在超过该数组长度的位置写入元素。请对输入的数组 就地 进行上述修改,不要从函数返回任何东西。

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

3. 快乐树

202. 快乐数https://leetcode.cn/problems/happy-number/

编写一个算法来判断一个数 n 是不是快乐数。

「快乐数」 定义为:

  • 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
  • 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
  • 如果这个过程 结果为 1,那么这个数就是快乐数。

如果 n快乐数 就返回 true ;不是,则返回 false

cpp 复制代码
class Solution {
public:
    int bitsum(int n)
    {
        int add=0,sum;
        while(n!=0)
        {
            sum=n%10;
            sum*=sum;
            n=n/10;
            
            add+=sum;
        }
        return add;
    }
    bool isHappy(int n)
    {
        int slow=n;
        int fast=bitsum(n);
        while(slow!=fast)
        {
            slow=bitsum(slow);
            fast=bitsum(bitsum(fast));
        }
        return slow==1;
    }
};

4. 盛水最多的容器

11. 盛最多水的容器https://leetcode.cn/problems/container-with-most-water/

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0)(i, height[i])

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

说明:你不能倾斜容器。


5. 有效三角形个数

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

给定一个包含非负整数的数组 nums ,返回其中可以组成三角形三条边的三元组个数。

cpp 复制代码
class Solution {
public:
    int triangleNumber(vector<int>& nums) {
        int i=0,count=0,left,right;
        sort(nums.begin(),nums.end());
        if(nums.size()<3)
        return 0;
        while(i<nums.size()-2)
        {
            left=i+1;
            while(left!=nums.size()-1)
            {
                right=nums.size()-1;
            while(right!=left)
            { 
                if (nums[left]+nums[right]>nums[i]&&
                nums[left]+nums[i]>nums[right])
                {
                    count=count+(right-left);
                    break;
                }
                else
                right--;
            }
                left++;
            }
            i++;
        }
        return count;
    }
};

6. 三数之和

15. 三数之和https://leetcode.cn/problems/3sum/

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != kj != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

cpp 复制代码
class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        vector<vector<int>> sv;
        int k=0,left,right,add;

        while(k<nums.size()-2)
        {
            left=k+1;
            right=nums.size()-1;
            while(left<right)
            {
                add=nums[k]+nums[left]+nums[right];
                //判断情况,区分进行
                if(add>0)
                right--;

                else if(add<0)
                left++;   

                else if(add==0)
                {
                    sv.push_back({nums[k],nums[left],nums[right]});
                    //跳过重复数
                    while(nums[left]==nums[left+1] && left+1<right)
                    left++;

                    while(nums[right]==nums[right-1] && right-1>left)
                    right--;
                    
                    left++;right--;
                }
                
            }
            k++;
            //跳过重复数
            while(nums[k]==nums[k-1] && k!=nums.size()-1)
            k++;
        }
            return sv;
    }
};

7. 四数之和

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

给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):

  • 0 <= a, b, c, d < n
  • abcd 互不相同
  • nums[a] + nums[b] + nums[c] + nums[d] == target

你可以按 任意顺序 返回答案 。

cpp 复制代码
class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        sort(nums.begin(),nums.end());
        vector<vector<int>> sv;
        int x=0,a;
        int k,left,right;
        long long add;
        if(nums.size()<4)
        return sv;
        while(x<nums.size()-3)
        {
            k=x+1;
            a=nums[x];
            
        while(k<nums.size()-2)
        {
            left=k+1;
            right=nums.size()-1;
            while(left<right)
            {
                add=(long long)nums[k]+nums[left]+nums[right];

                if(add>target-a)
                right--;
                else if(add<target-a)
                left++;
                else if(add==target-a)
                {
                    sv.push_back({nums[x],nums[k],nums[left],nums[right]});
                    while(nums[left]==nums[left+1] && left+1<right)
                    left++;
                    while(nums[right]==nums[right-1] && right-1>left)
                    right--;
                
                    left++;right--;
                }
                
            }
            k++;
            while(nums[k]==nums[k-1]&&k!=nums.size()-1)
            k++;
        }
            x++;
            while(nums[x]==nums[x-1]&&x!=nums.size()-1)
            x++;
        }
            return sv;
    }
};

相关推荐
2601_949817724 分钟前
C++指针与引用深度精讲:底层原理、差异对比与高阶实战陷阱
java·jvm·c++
va学弟12 分钟前
Java 网络通信编程(10):Channel 和 Selector
java·开发语言
爱吃提升23 分钟前
MATLAB impulse函数脉冲响应完整实操教程
开发语言·matlab
小饕31 分钟前
从 1080 Ti 到树莓派 4:Qwen2.5-0.5B Function Calling 端侧部署七步实战
开发语言·人工智能
Keven_1141 分钟前
算法札记:如何卡SPFA
算法·spfa
xian_wwq1 小时前
【学习笔记】OpenAI 兼容 API 服务化:从协议到 LLM Gateway(19/35)
笔记·学习
可编程芯片开发1 小时前
基于电压电流双闭环控制的三相整流器系统simulink建模与仿真
算法
糯米导航1 小时前
Rust + ONNX Runtime 构建生产级 AI 推理服务:从零到压测
开发语言·人工智能·rust
可编程芯片开发1 小时前
基于ADRC自抗扰算法的UAV飞行姿态控制系统simulink建模与仿真
算法
学究天人1 小时前
数学公理体系大全:第七章 连续统假设与力迫法简介
人工智能·算法·机器学习·数学建模·动态规划·图论·抽象代数