算法专题一: 双指针

news2025/1/11 4:16:19

目录

  • 前言
  • 1. 移动零(easy)
  • 2. 复写零(easy)
  • 3. 快乐数(medium)
  • 4. 盛水最多的容器(medium)
  • 5. 有效三角形的个数(medium)
  • 6. 和为 s 的两个数字(easy)
  • 7. 三数之和(medium)
  • 8. 四数之和(medium)

前言

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

1. 对撞指针: ⼀般用于顺序结构中,也称左右指针。

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

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

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

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

快慢指针的实现方式有很多种,最常用的⼀种就是:
• 在一次循环中,每次让慢的指针向后移动⼀位,而快的指针往后移动两位,实现一快一慢。

1. 移动零(easy)

题目链接:移动零

在这里插入图片描述
思想

在本题中,我们可以用一个 cur 指针来扫描整个数组,另一个 dest 指针用来记录非零数序列的最后一个位置。根据 cur 在扫描的过程中,遇到的不同情况,分类处理,实现数组的划分。

在这里插入图片描述

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

2. 复写零(easy)

题目链接: 复写零

在这里插入图片描述
算法思路

在这里插入图片描述

如果从前向后进行原地复写操作的话,由于0的出现会复写两次,导致没有复写的数被覆盖掉,因此我们选择从后往前的复写策略,但是从后往前复写的时候,我们需要找到最后一个复写的数,因此我们的大体流程分为两步:

  1. 先找到最后一个复写的数;
  2. 然后从后往前进行复写操作.
class Solution {
public:
    void duplicateZeros(vector<int>& arr) {
        int cur = 0, dest = -1;

        while(cur < arr.size())
        {
            if(arr[cur])
                ++dest;
            else
                dest+=2;
            if(dest >= arr.size()-1)
                break;
            ++cur;
        }
        if(dest == arr.size())
        {
            dest--;
            arr[dest--] = 0;
            cur--;
        }
        while(cur>=0)
        {
            if(arr[cur])
            {
                arr[dest--] = arr[cur--];
            }else
            {
                arr[dest--] = 0;
                arr[dest--] = 0;
                cur--;
            }

        }

    }
};

3. 快乐数(medium)

题目链接: 快乐数

在这里插入图片描述
算法思路

根据分析我们可以知道, 当重复执行x的时候, 数据就会陷入到一个循环中, 而快慢指针有一个特性,就是在一个圆圈中, 快指针总是会追上慢指针的,也就是说他们会相遇在一个位置上, 如果相遇位置的值是1, 那么这个数一定是快乐数, 如果相遇的位置不是1的话, 那么这个数就不是快乐数.

在这里插入图片描述

class Solution {
public:
    int mutify(int n)
    {
        int ret =  0;
        while(n)
        {
            int ge = n % 10;
            ret += ge*ge;
            n/=10;
        }
        return ret;
    }
    bool isHappy(int n) {
        int fast = mutify(n), slow = n;
        while(fast != slow)
        {
            fast = mutify(mutify(fast));
            slow = mutify(slow);
        }
        return fast==1;
    }
};

4. 盛水最多的容器(medium)

题目链接: 盛水最多的容器

在这里插入图片描述

算法思路

设置两个指针left,right分别指向容器的左右两个端点,此时容器的容积v = (right - left) * min(hegiht[right] , height[left]). 容器的左边界为height[left], 右边界为height[right].如果此时我们固定一个边界, 改变另一个边界,水的容积会有如下变化形式:

  1. 容器的宽度一定变小.
  2. 由于左边界较小, 决定了水的高度,如果改变左边界,新的水面高度不确定,但是一定不会超过右边的柱子高度,因此容器的容积可能会增大.
  3. 如果改变右边界,无论右边界移动到哪里,新的水面的高度一定不会超过左边界,也就是不会超过现在的水面高度,但是由于容器的宽度减小,因此容器的容积一定会变小.

由此我们可以left++跳过,舍弃左边界和它的组合情况,继续下一个判断, 不断重复, 就可以舍去大量不必要的枚举过程,直到left和right相遇.

在这里插入图片描述

class Solution {
public:
    int maxArea(vector<int>& height) {
        int left = 0, right = height.size()-1, ret = 0;
        while(left < right)
        {
            int v = min(height[left],height[right]) * (right - left);
            ret = max(v,ret);
            if(height[left]<height[right])
                left++;
            else right--;
        }
        return ret;
    }
};

5. 有效三角形的个数(medium)

题目链接: 有效的三角形个数

在这里插入图片描述
算法思路

在这里插入图片描述

class Solution {
public:
    int triangleNumber(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        int ret = 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])
                {
                    left++;
                }
                else
                {
                    ret+=right - left;
                    right--;
                }
            }  
        }
        return ret;
    }
};

6. 和为 s 的两个数字(easy)

题目链接: 查找总价格为目标值的两个商品

在这里插入图片描述算法思路

在这里插入图片描述

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

7. 三数之和(medium)

题目链接: 三数之和

在这里插入图片描述
算法思路

在这里插入图片描述

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        vector<vector<int>> vv;
       int n = nums.size();
       for(int i = 0; i<n;)
       {
            int target = -nums[i];
            int left = i+1,right = n-1;
            while(left<right)
            {
                int sum = nums[left]+nums[right];
                if(sum < target) left++;
                else if(sum > target) right--;
                else  
                {
                    vv.push_back({nums[left],nums[right],nums[i]});
                    left++,right--;
                    while(left<right&&nums[left]==nums[left-1]) left++;
                    while(left<right&&nums[right]==nums[right+1]) right--;
                }
            }
            i++;
            while(i<n&&nums[i]==nums[i-1]) i++;
       }
       return vv; 
    }
};

8. 四数之和(medium)

题目链接: 四数之和

在这里插入图片描述

算法思路

在这里插入图片描述

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        sort(nums.begin(),nums.end());
        vector<vector<int>> vv;
        int n = nums.size();
        for(int i = 0; i < n ;)
        {
            for(int j = i+1;j<n;)
            {
                long long a = (long long)target - nums[i] - nums[j];
                int left = j+1,right =n-1;
                while(left<right)
                {
                    int sum = nums[left] + nums[right];
                    if(sum<a) left++;
                    else if(sum>a) right--;
                    else
                    {
                        vv.push_back({nums[left],nums[right],nums[i],nums[j]});
                        left++,right--;
                        //去重1
                        while(left<right && nums[left] == nums[left-1]) left++;
                        while(left<right && nums[right] == nums[right+1]) right--;
                    }
                }
            j++;
            //去重2
            while(j<n && nums[j] == nums[j-1]) j++;
            }
        i++;
        while(i<n&&nums[i] == nums[i-1]) i++;    
        }
          return vv;
    }
  
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2112680.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux CentOS 7.9 安装mysql8

1、新建mysql文件夹 数据比较大&#xff0c;所以我在服务器另外挂了一个盘装mysql&#xff0c;和默认安装一个道理&#xff0c;换路径即可 cd ../ //创建文件夹 mkdir mysql //进入mysql文件夹 cd mysql 2、下载mysql8.0安装包并解压、重命名 //下载安装包 wget https://dev…

元宇宙先驱,城市区块链

blockcity 务实元宇宙的先行者,去中心化自治组织开放平台,轻松加入或创建你的DAO组织创新采用Web3和区块链思维,blockcity 真正人人可用,无需下载安装 《福建省元宇宙产业发展行动计划&#xff08;2024 — 2026 年&#xff09;在“促进数字创意产业发展”条目提到&#xff0c;…

ubuntu 20.04 一直卡在登录界面,即使密码正确也无法登录(失败记录)

ubuntu 20.04 一直卡在登录界面&#xff0c;即使密码正确也无法登录 这次是装实体机&#xff0c;一次失败的尝试。。。 名称型号CPUIntel Xeon E5-2673 V3GPURTX 3060 mobile 安装的时候不要选install third-party software for graphics and Wi-fi hardware and additional …

oracle锁的机制

文章目录 oracle锁的机制1. 概括2.锁的模式3.锁查看 死锁1. 说明2.死锁产生条件3.解决死锁冲突4. 事务和死锁预防总结 oracle锁的机制 1. 概括 1&#xff09;说明 锁是一种机制&#xff0c;多个事务同时访问一个数据库对象时&#xff0c;该机制可以实现对并发的控制 2&…

目标检测常见数据集格式

目标检测常见的数据集格式COCO、YOLO、VOC、DATA。 1、COCO 数据标注格式JSON&#xff0c;JSON文件中包含多个关键字段&#xff0c;如info、images、annotations等&#xff0c;分别存储了数据集的基本信息、图像信息和标注信息 COCO数据集的下载 官网地址&#xff1a;http://…

Computer Exercise

每日一练 单选题 在计算机机箱前面板接口插针上&#xff08;     C   &#xff09;表示复位开关。 A.SPK    B.PWRLED    C.RESET    D.HDDLED每台PC机最多可接&#xff08;     B   &#xff09;块IDE硬盘。 A.2    B.4    C.6    D.8&#xff08;    …

U盘怎么加密保护?U盘加密方法介绍

在数字化时代&#xff0c;U盘作为一种便携式存储设备&#xff0c;广泛应用于我们的日常生活和工作中。然而&#xff0c;U盘中存储的数据安全性问题日益凸显。为了保护个人隐私和重要数据&#xff0c;学会U盘加密方法显得尤为重要。本文将为您详细介绍几种U盘加密方法&#xff0…

用了虚拟机后,本机摄像头打不开了(联想电脑thinkpad)

虚拟机有摄像头&#xff0c;我断开了连接&#xff0c;现在本机的摄像头打开就是一个锁 我先把虚拟机的摄像头关了 然后把本机的vm usb关闭了 WinR&#xff09;&#xff0c;输入services.msc&#xff0c;找到VMware USB Arbitration Service&#xff0c;确保其状态为“关闭 然后…

UniApp实现漂亮的音乐歌词滚动播放效果

在现代的音乐播放应用中&#xff0c;歌词的展示和滚动播放已经成为了一个非常常见的功能。今天&#xff0c;我们将通过UniApp来实现一个漂亮的歌词滚动播放功能。我们将使用UniApp提供的组件和API来完成这个任务。 页面结构 在页面的模板部分&#xff0c;我们需要创建一个音频…

实现简单聊天

管道通信 目的&#xff1a; 实现 xxz 与 zy 之间的通讯聊天 功能&#xff1a; 同一网络下进行的模拟通讯实现 缺点&#xff1a;没有涉及到网络的通信&#xff0c;只是简单的进程之间模拟的通信 采用到的技术点&#xff1a; 1 有名管道 优点&#xff1a; 在文件系统中作为一…

c++修炼之路之特殊类设计与类型转换

目录 一&#xff1a;特殊类设计 1.设计一个不能被拷贝的类 2.设计一个只能在堆上创建对象的类 3.设计一个只能在栈上创建对象的类 4.设计一个不能被继承的类 5.设计一个只能创建一个对象的类(单例模式) 二&#xff1a;c的类型转换 1.自定义类型&#xff0c;内置类型…

计算机的错误计算(八十五)

摘要 计算机的错误计算&#xff08;八十一&#xff09;至&#xff08;八十四&#xff09;介绍了双曲正弦、余弦、正割以及余割函数的计算精度问题。本节说明导致这些计算错误的主要原因。 首先&#xff0c;双曲正弦、余弦、正割以及余割函数主要包括 与 的计算&#xff0c;以…

逐行讲解Transformer的代码实现和原理讲解:nn.Linear线性层原理

视频详细讲解&#xff1a;LLM模型&#xff1a;代码讲解Transformer运行原理(1)_哔哩哔哩_bilibili 1 概述 经过Transformer的12个块处理完之后&#xff0c;4批文本数据得到了一个矩阵[4, 8, 16]&#xff0c;也就是每批数据都训练出了一个结果&#xff0c;在训练阶段&#xff…

Netty系列-3 ChannelFuture和ChannelPromise介绍

背景 Netty源码中大量使用了Future和Promise&#xff0c;学习ChannelFuture和ChannelFuture有助于理解Netty的设计思路。 本文的重点内容在于梳理清楚这些类的关系以及结合源码实现介绍这些类的作用&#xff0c;其中核心逻辑在于DefaultPromise和DefaultChannelPromise&#x…

GBase8sV8.8安装指南

目录 一、下载 Gbase 安装包二、安装预置条件1.确保安装包和平台适配2.安装依赖包&#xff1a;jdk(1.6版本以上)、unzip、libaio、libgcc、libstdc、ncurses、pam&#xff0c;如果缺失请提前安装 三、上传包并解压四、安装五、登录并创建数据库六、启动停止数据库七、常见问题八…

虚拟机ubuntu与主机共享文件夹

现在主机&#xff08;windows&#xff09;上新建一个共享文件夹 打开虚拟机 按下面操作打开共享文件夹 进入虚拟机的系统 cd /mnt/hgfs 如果报错 可以按下面的解决 挂载一下 sudo mount -t fuse.vmhgfs-fuse .host:/ /mnt/hgfs -o allow_other 如果显示不存在这个文…

session机制

场景&#xff1a;当众多用户访问网站&#xff0c;发出HTTP请求&#xff0c;那么网站是如何判断哪个HTTP请求对应的是哪个用户 &#xff1f; 作用&#xff1a;用于服务端区分用户。 当用户使用客户端登录时&#xff0c;服务端会进行验证&#xff0c;验证通过后会为这次登录创建…

剖析Cookie的工作原理及其安全风险

Cookie的工作原理主要涉及到HTTP协议中的状态管理。HTTP协议本身是无状态的&#xff0c;这意味着每次请求都是独立的&#xff0c;服务器不会保留之前的请求信息。为了在无状态的HTTP协议上实现有状态的会话&#xff0c;引入了Cookie机制。 1. Cookie定义 Cookie&#xff0c;也…

EMC测试

传导干扰测试&#xff1a; 现场实录CE传导骚扰电压测试&#xff0c;硬件环境&#xff1a; R&S EPL1000 EMI测量接收机&#xff08;支持时域测试&#xff09; R&S ENV216人工电源网络 R&S ELEKTRA 测试软件 黑色底板&#xff0c;不写丝印&#xff0c;0402封装平行排…

Tomcat服务详解

一、部署Tomcat服务器 JDK安装官方网址&#xff1a;https://www.oracle.com/cn/java Tomcat安装官方网址&#xff1a;Apache Tomcat - Welcome! 安装JDK 1.获取安装包 wget https://download.oracle.com/otn/java/jdk/8u411-b09/43d62d619be4e416215729597d70b8ac/jdk-8u41…