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;
    }
};
相关推荐
lilili也38 分钟前
visual studio add matlab
c语言·c++
福如意如我心意1 小时前
java虚拟线程和Go协程的区别
开发语言
weixin_440784111 小时前
Java基础常见题
java·开发语言·python·java基础
(Charon)1 小时前
【C++】多线程死锁:产生原因、复现与解决方法
开发语言·c++·算法
跨境小彭2 小时前
Python列表去重的6种高效方法(含保留顺序+性能对比)
开发语言·python
今天AI了吗2 小时前
Python 基础语法从入门到使用详解
开发语言·人工智能·python
oier_Asad.Chen2 小时前
【洛谷题解/AcWing题解/真题】洛谷P2330【SCOI2005】繁忙的都市(Kruskal算法的再探究))
c++·算法·贪心算法·图论·最小生成树·kruskal
雪之下雪乃的代码日记2 小时前
Python快速入门(Java开发者版)
java·开发语言·笔记·python
Y3815326623 小时前
SERP API 请求体 Gzip 压缩优化实战:大数据量降带宽 80%
开发语言·前端·php
weixin199701080163 小时前
☁️《抖店API基础¥0.018/百次·增值¥0.05/百次:云内云外价差架构实战》(附Python源码)
开发语言·python·架构