【算法从零到千】【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;
    }
};

相关推荐
小许同学记录成长1 小时前
孔洞修补算法
算法
Irissgwe1 小时前
一、Qt 概述
c++·qt·gui·qt creator
随意起个昵称1 小时前
线性dp-计数类题目9(斐波那契字符串)
算法·动态规划
超梦dasgg1 小时前
Java 正则表达式 完整详解(语法 + 核心类 + 常用方法 + 实战案例)
java·开发语言·正则表达式
方也_arkling1 小时前
【Java-Day17】API篇-BigInteger和BigDecimal
java·开发语言
星辰_mya1 小时前
ThreadLocal之微服务链路追踪
java·开发语言·前端
m0_617493941 小时前
PySide6/PyQt6实现中英文切换完整教程(Qt Designer + Qt Linguist + 动态切换)
开发语言·qt
chushiyunen1 小时前
elasticsearch内置接口笔记
大数据·笔记·elasticsearch
菜菜的顾清寒1 小时前
力扣HOT100(49)动态规划 -- 打家劫舍
算法·leetcode·动态规划