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;
    }
};
相关推荐
第九序言T4 小时前
Python 数据处理进阶(十八)批量处理同结构文件:一个文件夹一次跑完
开发语言·python·自动化·pandas·数据处理
Sakura_j_h_4 小时前
EasyEDA PCB 快速设计Skills
c++·python·github
龙亘川5 小时前
构建城市公共安全数字底座:亘川智城智慧安防系统全维度解读
java·大数据·开发语言·人工智能·信息可视化
程序喵大人5 小时前
【C++入门】内存模型与资源管理 - 09 shared_ptr 和 weak_ptr 解决共享,也带来代价
开发语言·c++·资源管理·智能指针·内存模型
Raas1006 小时前
AI网关部署方案?从部署到上线全流程
java·开发语言·人工智能·gateway·ai网关·企业级ai网关·企业级ai产品
专注仿真6 小时前
线性回归和逻辑回归算法详解
开发语言·人工智能·python·大模型训练·控制算法
jimy17 小时前
C++ 中的 `T&&`:右值引用与转发引用
开发语言·c++
呆呆虫127 小时前
用 orjson 加速 SerpBase 响应解析:基准对比与注意事项
开发语言·php
心疼你的一切8 小时前
Python自动发邮件实战定时发报表
大数据·开发语言·python
Wang's Blog9 小时前
Java 项目实战:交友项目 - 用户体系集成总结
java·开发语言·交友