C++算法之双指针算法

1089.复写0

算法原理

解法双指针算法:

1.先找到最后一个复写的数;

这里同样也可以使用双指针算法

初始化

根据cur遇到的值来选择dest的移动步数,当dest到数组末尾时,cur所在位置就是最后一个复写的数

注意一下可能出现的越界情况

2.之后从后向前完成复写操作;

遇到非零数就正常拷贝复写,遇到零就复写拷贝两次

cpp 复制代码
1class Solution
2 {
3public:
4    void duplicateZeros(vector<int>& arr) 
5    {
6        //先找到最后一个复写数
7        int cur = 0,dest = -1,n = arr.size();
8        while(cur < n )
9        {
10            if(arr[cur])
11            {
12                dest++;
13            }
14            else
15            {
16                dest += 2;
17            }
18            if(dest >= n-1)
19            {
20                break;
21            }
22            cur++;
23        }
24      //处理边界情况
25      if(dest == n)
26      {
27        arr[n-1] = 0;
28        cur--;dest -=2;
29      }
30      //从后向前完成复写操作
31      while(cur >= 0)
32      {
33        if(arr[cur])
34        {
35            arr[dest] = arr[cur];
36            dest--;
37            cur--;
38        }
39        else
40        {
41          arr[dest--] = 0;
42          arr[dest--] = 0;
43          cur--;
44        }
45      }
46    }
47};

202.快乐数

算法原理:

这个类似约瑟夫环,由题目可知这个会是一个循环,就代表一个数无论从哪里开始,走多少步,最后一定会进入一个循环,这个时候就可以使用快慢指针,一个数在前一个数在后,一个一次走一步另一个一次走两步,这两个数一定会相遇,相遇时有两种情况,情况一:快指针在1处循环,慢指针追上,也在1处循环,情况二:快指针走过一遍循环,追上慢指针,那我们就可以在相遇处判断是否为1来输出结果

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

15,三数之和

算法原理:

解法一:排序+暴力+set去重

就是先排序,然后进行三次遍历,然后使用set容器去重

解法二:排序+双指针

首先先进行排序,然后从左到0依次固定数,然后再右边区间内进行双指针算法找到固定数的相反数

1.去重:当找到一种结果后两个指针都要跳过重复元素,使用完一次双指针后,固定的数也要去重

注意指针越界问题

2.不漏:找到一种结果后,不要停,缩小区间,继续寻找

cpp 复制代码
1class Solution {
2public:
3    vector<vector<int>> threeSum(vector<int>& nums) {
4        vector<vector<int>> ret;
5        sort(nums.begin(),nums.end());
6        int n = nums.size();
7        for(int i = 0; i < n;)
8        {
9            if(nums[i] > 0)
10            {
11                break;
12            }
13            int left = i+1, right = n-1;
14            while(left < right)
15            {
16                if(left < right && nums[left] + nums[right] > -nums[i])
17                right--;
18                else if( left < right && nums[left] + nums[right] < -nums[i])
19                left++;
20                else{
21                    ret.push_back({nums[i],nums[left],nums[right]});
22                    right--;
23                    left++;
24                    while(left<right && nums[right] == nums[right+1])
25                    {
26                        right--;
27                    }
28                    while(left < right && nums[left] == nums[left-1])
29                    {
30                        left++;
31                    }
32                }
33            }
34            while(i+1 < n && nums[i] == nums[i+1])
35            {
36                i++;
37            }
38            i++;
39        }
40        return ret;
41    }
42};

18.四数之和

算法原理:

解法一:排序+暴力枚举+set去重

解法二:排序+双指针

1.依次固定一个数a;

2.在a后面的区间内,利用"三数之和"找到三个数,使这三个数的和等于target - a即可

{

1.在前面的基础上,依次固定一个数b;

2.在b后面区间内,利用"双指针"找到两个数,使这两个数的和等于target-a-b

}(嵌套解法)

cpp 复制代码
class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector<vector<int>> ret;
        //1.排序
     sort(nums.begin(),nums.end());
      //2.利用双指针解决问题
      int n = nums.size();
      for(int i =0; i <n;)//固定数a
      {
        //利用三数之和解决问题
        for(int j = i+1; j <n;)//固定数b
        {
            //双指针解法
            int left = j+1,right = n-1;
            long long aim = (long long)target -nums[i] - nums[j];
            while(left < right)
            {
                int sum = nums[left] + nums[right];
                if(sum< aim)left++;
                else if( sum > aim)right--;
                else
                {
                   ret.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 ret;
    }
};
相关推荐
神仙别闹2 小时前
基于 C++ 实现(控制台)学生成绩管理系统
开发语言·c++
会周易的程序员2 小时前
5 节点边缘冗余方案(上):基于 aiRaft 的物联网高可用控制面设计
c++·分布式·物联网·raft·iot·共识
伞伞悦读3 小时前
【第36期】Python 目录与路径详解:pathlib、文件遍历、创建、复制、移动和删除风险
开发语言·python
qq_199886876 小时前
第6板块·第4节:构建系统与多文件项目
c++·人工智能·gpu算力
2601_966949656 小时前
只拿到股票代码还不够:量化程序到底还需要哪些标的信息?——从数据建模开始理解股票元数据
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
m0_734571766 小时前
深入理解5g <十八>传输块tbsize的计算
开发语言·5g
汉克老师7 小时前
GESP2026年9月认证C++三级( 第三部分编程题(2、分割字符串))精讲
c++·gesp·小学生·学c++编程
估值探索者7 小时前
【Python量化系统工程化 #08】关了 SSH 就停?systemd 让脚本开机自启 + 异常自动拉起
java·c++·人工智能·分类·数据挖掘
RAN11426760087 小时前
1.3第一个程序的介绍
开发语言·qt
天若有情6737 小时前
C++花式魔改!手写头文件复刻Java语法,彻底打破编码思维定式
java·c++·语言做语言·jac++