【双指针】算法题(一)

embedded/2024/12/20 6:15:31/

【双指针】算法题(一)

前言:

本章只有两道算法题:移动零、复写零。

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

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

2.**快慢指针:**基本思想就是使用两个移动速度不同的指针在数组或链表等序列结构上移动。(就不如链表使用的快慢指针,每次fast向后移动两步,slow向后移动一位,两个指针速度不同)

题目一:移动零

题目链接在这里,点击即可

题目描述:
在这里插入图片描述

算法分析:

  1. 先定义两个指针,cur 和 dest ,cur 用来遍历数组,dest用来记录数组的最后一个元素的位置。
  2. 先思考,本题要求在一个数组里面实现把零全部移动到数组的后面,cur 在遍历数组的时候,会遇到不同的情况:使[0, dest] 的元素全部都是非零元素, [dest + 1, cur - 1] 的 元素全是零。

算法流程:

  1. 定义两个指针,int cur=0(用于遍历数组);int dest=-1(指向非零元素序列的最后⼀个位置。 因为刚开始我们不知道最后⼀个非零元素在什么位置,因此初始化为-1);cur不大于数组元素个数。
  2. 开始时,首先移动cur,若cur指向的元素的值为0,dest不变,cur继续向后移动;若cur指向的元素的值不为零,则dest向后移动一位,然后与cur指向的元素进行交换,然后cur再向后移动一位。

算法代码1(这是用for循环的):

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

算法代码2(这是用while循环的,思路跟上面一样,只是代码展现形式不一样,用while循环两个指针的起始位置可以是相同的):

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

题目二:复写零

题目链接在这里

题目描述:
在这里插入图片描述

算法分析:

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

  • 先找到最后一个复写的数
  • 然后再从后向前复写0

算法流程:

  1. 先定义两个指针,int cur=0;int dest=0;
  2. 然后找到最后一个复写的数
    • cur小于arr.size(),判断cur位置的值,用cur从前往后遍历,当cur遇到0,dest向后移动两位;当cur遇到不为0的数时,dest向后移动一位。
    • 判断dest是否到达数组的最后一位,终止循环,若没有到达,则cur继续往后移动一位,继续判断。
  3. 判断dest是否越界(这里是考虑一种特殊的情况,当cur位置的是0的时候,dest位于数组的倒数第二位,再复写的时候有一个0是越界了的)
    • 若dest越界,则让arr[arr.size()-1]=0;
    • 然后让cur往前移动一位,dest往前移动两位,即cur–,dest-=2
  4. 最后从后往前遍历
    • 如果cur位置的值为0,则arr[dest–]=0;arr[dest–]=0,(这步复写0,所以写两次arr[dest–]=0);
    • 如果cur位置的值不为0,则将arr[cur–]值赋给arr[dest–]

代码实现:

class Solution {
public:void duplicateZeros(vector<int>& arr) {int cur=0;int dest=-1;while(cur<arr.size()){if(arr[cur]==0){dest+=2;}else{dest++;}if(dest>=arr.size()-1){break;}cur++;}if(dest==arr.size()){arr[arr.size()-1]=0;cur--;dest-=2;}while(cur>=0){if(arr[cur]==0){arr[dest--]=0;arr[dest--]=0;cur--;}else{arr[dest--]=arr[cur--];}}}
};

http://www.ppmy.cn/embedded/147199.html

相关文章

【Python使用】嘿马头条项目从到完整开发教程第9篇:缓存,1 缓存穿透【附代码文档】

本教程的知识点为:简介 1. 内容 2. 目标 产品效果 ToutiaoWeb虚拟机使用说明 数据库 理解ORM 作用 思考&#xff1a; 使用ORM的方式选择 数据库 SQLAlchemy操作 1 新增 2 查询 all() 数据库 分布式ID 1 方案选择 2 头条 使用雪花算法 &#xff08;代码 toutiao-backend/common/…

【中标麒麟服务器操作系统实例分享】java应用DNS解析异常分析及处理

了解更多银河麒麟操作系统全新产品&#xff0c;请点击访问 麒麟软件产品专区&#xff1a;https://product.kylinos.cn 开发者专区&#xff1a;https://developer.kylinos.cn 文档中心&#xff1a;https://documentkylinos.cn 情况描述 中标麒麟服务器操作系统V7运行在 ARM虚…

无管理员权限 LCU auth-token、port 获取(全网首发 go)

一&#xff1a; 提要&#xff1a; 参考项目&#xff1a; https://github.com/Zzaphkiel/Seraphine 想做一个 lol 查战绩的软件&#xff0c;并且满足自己的需求&#xff08;把混子和大爹都表示出来&#xff09;&#xff0c;做的第一步就是获取 lcu token &#xff0c;网上清一色…

白话java设计模式

创建模式 单例模式&#xff08;Singleton Pattern&#xff09;&#xff1a; 就是一次创建多次使用&#xff0c;它的对象不会重复创建&#xff0c;可以全局来共享状态。 工厂模式&#xff08;Factory Method Pattern&#xff09;&#xff1a; 可以通过接口来进行实例化创建&a…

快速在远程服务器执行命令、批量在多个服务器执行命令(基于sshpass的自定义脚本fastsh)

在日常服务器操作中&#xff0c;很多时候我们需要同时操作多个服务器。特别对于那些每个服务器都需要操作相同命令的场景&#xff0c;不断的切换命令会话窗口会比较麻烦。基于此&#xff0c;编写了本文中的 fastsh 脚本用于轻度解决这种问题&#xff0c;提高一定的便利性。 使…

【排序算法】——选择排序

前言 排序(Sorting) 是计算机程序设计中的一种重要操作&#xff0c;它的功能是将一个数据元素&#xff08;或记录&#xff09;的任意序列&#xff0c;重新排列成一个关键字有序的序列。所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#x…

【Latex手册】自用

收录Latex使用文档/工具 个人使用时候的tips&#xff0c;仅供个人使用 核心网页&#xff1a;LaTeX 工作室 【1】首页 | LaTeX 知识库 &#xff08;有详细的入门教程&#xff09; 【2】LaTeX工作室 - LaTeX工作室&#xff08;一些模板&#xff09; 【3】LaTeX 工作室 &…

【Rust自学】3.6. 控制流:循环

3.6.0. 写在正文之前 欢迎来到Rust自学的第三章&#xff0c;一共有6个小节&#xff0c;分别是: 变量与可变性数据类型&#xff1a;标量类型数据类型&#xff1a;复合类型函数和注释控制流&#xff1a;if else控制流&#xff1a;循环&#xff08;本文&#xff09; 通过第二章…