双指针_算法

目录

[0. 双指针](#0. 双指针)

[1. 移动零](#1. 移动零)

[1.1 题目链接](#1.1 题目链接)

[1.2 题目描述](#1.2 题目描述)

[1.3 算法思路](#1.3 算法思路)

[1.4 C++算法代码](#1.4 C++算法代码)

[2. 复写零](#2. 复写零)

[2.1 题目链接](#2.1 题目链接)

[2.2 题目描述](#2.2 题目描述)

[2.3 算法思路](#2.3 算法思路)

[2.4 C++算法代码](#2.4 C++算法代码)

[3. 快乐数](#3. 快乐数)

[3.1 题目链接](#3.1 题目链接)

[3.2 题目描述](#3.2 题目描述)

[3.3 算法思路](#3.3 算法思路)

[3.4 C++算法代码](#3.4 C++算法代码)

[4. 盛最多水的容器](#4. 盛最多水的容器)

[4.1 题目链接](#4.1 题目链接)

[4.2 题目描述](#4.2 题目描述)

[4.3 算法思路](#4.3 算法思路)

[4.4 C++算法代码](#4.4 C++算法代码)

[5. 有效三角形的个数](#5. 有效三角形的个数)

[5.1 题目链接](#5.1 题目链接)

[5.2 题目描述](#5.2 题目描述)

[5.3 算法思路](#5.3 算法思路)

[5.4 C++算法代码](#5.4 C++算法代码)

6.和为s的两个数

[6.1 题目链接](#6.1 题目链接)

[6.2 题目描述](#6.2 题目描述)

[6.3 算法思路](#6.3 算法思路)

[6.4 C++算法代码](#6.4 C++算法代码)

[7. 三数之和](#7. 三数之和)

[7.1 题目链接](#7.1 题目链接)

[7.2 题目描述](#7.2 题目描述)

[7.3 算法思路](#7.3 算法思路)

[7.4 C++算法代码](#7.4 C++算法代码)


0. 双指针

常见的双指针有两种形式,一种是对撞指针,一种是左右指针。

**对撞指针:**一般用于顺序结构中,也称左右指针。

  • 对撞指针从两端向中间移动。一个指针从左端开始,另一个从右端开始,然后逐渐往近。
  • 对撞指针的终止条件一般是两个指针相遇或者错开(也可能在循环内部找到结果直接跳出环),也就是:

left == right (两个指针指向同一个位置)

left > right(两个指针错开)

**快慢指针:**又称为龟兔赛跑算法,其基本思想就是使用两个移动速度不同的指针在数组或链表等序列结构上的移动。

这种方法对于处理环形链表或数组非常有用。

其实不单单是环形链表或者数组,如果我们要研究的问题出现循环往复的情况时,均可考虑使用快慢指针的思想。

快慢指针的实现方式有很多种,最常用的一种就是:

  • 在一次循环中,每次让慢的指针向后移动一位,而快的指针往后移动两位,实现一快一慢。

代码链接:

OptimalAlgorithm: OptimalAlgorithm - Gitee.comhttps://gitee.com/Axurea/optimal-algorithm/tree/master/2024_10_7_Algorithm

1. 移动零

1.1 题目链接

283. 移动零 - 力扣(LeetCode)https://leetcode.cn/problems/move-zeroes/description/

1.2 题目描述

1.3 算法思路

1.4 C++算法代码

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

2. 复写零

2.1 题目链接

1089. 复写零 - 力扣(LeetCode)https://leetcode.cn/problems/duplicate-zeros/description/

2.2 题目描述

2.3 算法思路

2.4 C++算法代码

cpp 复制代码
class Solution {
public:
    void duplicateZeros(vector<int>& arr)
    {
        int cur = 0,dest = -1;
        //找最后一个复写的数
        while(cur < arr.size())
        {
            if(arr[cur] != 0)
                dest++;
            else
                dest +=2;
            if(dest >= arr.size()-1) break;
            cur++;
        }
        //处理一下边界情况
        if(dest == arr.size())
        {
            arr[dest-1] = 0;
            cur--;
            dest-=2;
        }
        //复写操作
        while(cur >= 0)
        {
            if(arr[cur] != 0)
            {
                arr[dest--] = arr[cur--];
            }
            else
            {
                arr[dest--] = arr[cur];
                arr[dest--] = arr[cur--];
                
            }
        }
    }
};

3. 快乐数

3.1 题目链接

. - 力扣(LeetCode). - 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/happy-number/description/

3.2 题目描述

3.3 算法思路

3.4 C++算法代码

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

4. 盛最多水的容器

4.1 题目链接

11. 盛最多水的容器 - 力扣(LeetCode)https://leetcode.cn/problems/container-with-most-water/description/

4.2 题目描述

4.3 算法思路

4.4 C++算法代码

cpp 复制代码
class Solution {
public:
    int maxArea(vector<int>& height) {
        int left = 0,right = height.size()-1,max = 0,v = 0;
        while(left < right)
        {
            v = (height[left] > height[right] ? height[right] : height[left]) *  (right - left);
            if(v > max) max = v;
            height[left] > height[right] ? right-- : left++;
        }
        return max;
    }
};

5. 有效三角形的个数

5.1 题目链接

611. 有效三角形的个数 - 力扣(LeetCode)https://leetcode.cn/problems/valid-triangle-number/description/

5.2 题目描述

5.3 算法思路

5.4 C++算法代码

cpp 复制代码
class Solution {
public:
    int triangleNumber(vector<int>& nums) {
        //排序优化
        sort(nums.begin(),nums.end());
        //利用双指针解决问题
        int value = 0;
        for(int i = nums.size()-1;i >= 2;i--)
        {
            int left = 0,right = i -1;
            while(left < right)
            {
                if(nums[left] + nums[right] > nums[i])
                {
                    value += right - left;
                    right--;
                }
                else
                {
                    left++;
                }
            }
        }
        return value;
    }
};

6.和为s的两个数

6.1 题目链接

LCR 179. 查找总价格为目标值的两个商品 - 力扣(LeetCode)https://leetcode.cn/problems/he-wei-sde-liang-ge-shu-zi-lcof/description/

6.2 题目描述

6.3 算法思路

6.4 C++算法代码

cpp 复制代码
class Solution {
public:
    vector<int> twoSum(vector<int>& price, int target) {
        int left = 0,right = price.size()-1;
        while(left < right)
        {
            int sum = price[left] + price[right];
            if(sum < target)
                left++;
            else if(sum > target)
                right--;
            else
                return {price[left],price[right]};
        }
        return {-4941, -1};
    }
};

7. 三数之和

7.1 题目链接

15. 三数之和 - 力扣(LeetCode)https://leetcode.cn/problems/3sum/description/

7.2 题目描述

7.3 算法思路

7.4 C++算法代码

cpp 复制代码
class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        sort(nums.begin(),nums.end());
        vector<vector<int>> ret;
        int n = nums.size();
        for(int i = 0;i < n;)
        {
            int x = nums[i];
            for(int j = i + 1;j < n;)
            {
                int begin = j + 1,end = n - 1;
                long long z = (long long)target - nums[i] - nums[j];
                while(begin < end)
                {
                    int sum = nums[begin] + nums[end];
                    if(sum < z) begin++;
                    else if(sum > z) end--;
                    else
                    {
                        ret.push_back({nums[i],nums[j],nums[begin],nums[end]});
                        begin++;
                        while(begin < end && nums[begin] == nums[begin-1]) begin++;
                        end--;
                        while(begin < end && nums[end] == nums[end+1]) end--;
                    }
                }
                j++;
                while(j < n && nums[j] == nums[j-1]) j++;
            }
            i++;
            while(i < n && nums[i] == nums[i-1]) i++;
        }
        return ret;
    }
};
相关推荐
IronmanJay1 小时前
【LeetCode每日一题】——862.和至少为 K 的最短子数组
数据结构·算法·leetcode·前缀和·双端队列·1024程序员节·和至少为 k 的最短子数组
IT规划师4 小时前
数据结构 - 散列表,三探之代码实现
数据结构·散列表·哈希表
武子康5 小时前
大数据-187 Elasticsearch - ELK 家族 Logstash Filter 插件 使用详解
大数据·数据结构·elk·elasticsearch·搜索引擎·全文检索·1024程序员节
韭菜盖饭7 小时前
LeetCode每日一题3211---生成不含相邻零的二进制字符串
数据结构·算法·leetcode
czme7 小时前
线程和进程
linux·数据结构·计算机网络
J_admin9 小时前
数据结构 之 二叉树的遍历------先根遍历(五)
数据结构
黑不拉几的小白兔14 小时前
PTA L1系列题解(C语言)(L1_097 -- L1_104)
数据结构·算法·1024程序员节
秋说14 小时前
【数据结构 | PTA】懂蛇语
数据结构·c++
ChaoZiLL15 小时前
关于我的数据结构与算法——初阶第二篇(排序)
数据结构·算法
single59416 小时前
【综合算法学习】(第十篇)
java·数据结构·c++·vscode·学习·算法·leetcode