LeedCode刷题---双指针问题

顾得泉:个人主页

个人专栏:《Linux操作系统》  《C/C++》  《LeedCode刷题》

键盘敲烂,年薪百万!


双指针简介

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

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

       对撞指针从两端向中间移动。一个指针从最左端开始,另一个从最右端开始。然后逐渐往中间逼近。

       对撞指针的终止条件一般是两个指针相遇或者错开(也可能在循环内部找到拿果直接跳出循
环),也就是:

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

       left > right(两个指针错开)

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

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

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

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


一、移动零

题目链接:移动零

题目描述

       给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

       请注意 ,必须在不复制数组的情况下原地对数组进行操作。

示例 1:

输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]

示例 2:

输入: nums = [0]
输出: [0]

提示:

  • 1 <= nums.length <= 104
  • -231 <= nums[i] <= 231 - 1

解法

算法思路:

       在本题中,我们可以用一个cur 指针来扫描整个数组,另一个dest指针用来记录非零数序列的最后一个位置。根据cur在扫描的过程中,遇到的不同情况,分类处理,实现数组的划分。在cur遍历期间,使[0, dest]的元素全部都是非零元素,[dest + 1, cur - 1]的元素全是零。

算法流程:

       a.初始化 cur = 0(用来遍历数组),dest = -1(指向非零元素序列的最后一个位置。因为刚开始我们不知道最后一个非零元素在什么位置,因此初始化为-1)

       b.cur依次往后遍历每个元素,遍历到的元素会有下面两种情况

       i.遇到的元素是0 ,cur直接++。因为我们的目标是让[dest + 1, cur - 1]内的元素全都是零,因此当cur遇到o的时候,直接++,就可以让 o_在cur - 1的位置上,从而在[dest + 1, cur - 1]内;

       ii.遇到的元素不是0,dest++,并且交换cur位置和dest位置的元素,之后让cur++,扫描下一个元素。

       因为dest指向的位置是非零元素区间的最后一个位置,如果扫描到一个新的非零元素,那么它的位置应该在dest +1的位置上,因此dest先自增1;

       dest++之后,指向的元素就是0元素(因为非零元素区间末尾的后一个元素就是0)因此可以交换到cur所处的位置上,实现[0,dest]的元素全部都是非零元素,[dest+ 1, cur - 1]的元素全是零

代码实现

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

二、复写零

题目链接:复写零

题目描述

       给你一个长度固定的整数数组 arr ,请你将该数组中出现的每个零都复写一遍,并将其余的元素向右平移。

       注意:请不要在超过该数组长度的位置写入元素。请对输入的数组 就地 进行上述修改,不要从函数返回任何东西。

示例 1:

输入:arr = [1,0,2,3,0,4,5,0]
输出:[1,0,0,2,3,0,0,4]
解释:调用函数后,输入的数组将被修改为:[1,0,0,2,3,0,0,4]

示例 2:

输入:arr = [1,2,3]
输出:[1,2,3]
解释:调用函数后,输入的数组将被修改为:[1,2,3]

提示:

  • 1 <= arr.length <= 104
  • 0 <= arr[i] <= 9

解法

算法思路:

       如果「从前向后」进行原地复写操作的话,由于/的出现会复写两次,导致没有复写的数「被覆盖掉」。因此我们选择「从后往前」的复写策略。

       但是「从后向前」复写的时候,我们需要找到「最后一个复写的数」,因此我们的大体流程分两步:

       i.先找到最后一个复写的数;

       ii.然后从后向前进行复写操作

算法流程:

a.初始化两个指针cur=0, dest = 0;

b.找到最后一个复写的数︰

     i. 当cur <n的时候,一直执行下面循环:

       判断cur位置的元素:

       如果是0的话,dest往后移动两位;。否则,dest往后移动一位

       判断dest时候已经到结束位置,如果结束就终止循环;

       如果没有结束,cur++,继续判断

c.判断dest是否越界到n的位置:

     i.如果越界,执行下面三步:

       1. n - 1位置的值修改成0;

       2. cur向移动一步;

       3. dest向前移动两步

d. 从cur位置开始往前遍历原数组,依次还原出复写后的结果数组:

     i.判断cur位置的值:

       1.如果是0 :dest以及dest - 1位置修改成0,dest -= 2

       2.如果非零:dest位置修改成0,dest -= 1 ;

     ii. cur--,复写下一个位置

代码实现

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

三、快乐数

题目链接:

题目描述

        编写一个算法来判断一个数 n 是不是快乐数。

「快乐数」 定义为:

  • 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
  • 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
  • 如果这个过程 结果为 1,那么这个数就是快乐数。

如果 n 是 快乐数 就返回 true ;不是,则返回 false 

示例 1:

输入:n = 19
输出:true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1

示例 2:

输入:n = 2
输出:false

提示:

  • 1 <= n <= 231 - 1

解法

算法思路:

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

补充知识:

       如何求一个数n每个位置上的数字的平方和

a.把数n每一位的数提取出来:

     循环迭代下面步骤:

        i.int t = n % 10提取个位;

        ii. n /= 10干掉个位;

       直到n的值变为0 ;

b.提取每一位的时候,用一个变量tmp记录这一位的平方与之前提取位数的平方和

       tmp = tmp + t * t

代码实现

class Solution 
{
public:int Sum(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 = Sum(n);while(slow != fast){slow = Sum(slow);fast = Sum(Sum(fast));}return slow == 1;}
};

结语:今日的刷题分享到这里就结束了,希望本篇文章的分享会对大家的学习带来些许帮助,如果大家有什么问题,欢迎大家在评论区留言~~~ 

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Filament】Filament环境搭建

1 前言 Filament 是一个实时物理渲染引擎&#xff0c;用于 Android、iOS、Linux、macOS、Windows 和 WebGL 平台。该引擎旨在提供高效、实时的图形渲染&#xff0c;并被设计为在 Android 平台上尽可能小而尽可能高效。Filament 支持基于物理的渲染&#xff08;PBR&#xff09;&…

论文学习-Bert 和GPT 有什么区别?

Foundation Models, Transformers, BERT and GPT 总结一下&#xff1a; Bert 是学习向量表征&#xff0c;让句子中某个词的Embedding关联到句子中其他重要词。最终学习下来&#xff0c;就是词向量的表征。这也是为什么Bert很容易用到下游任务&#xff0c;在做下游任务的时候&a…

python pyaudio实时读取音频数据并展示波形图

python pyaudio实时读取音频数据并展示波形图 下面代码可以驱动电脑接受声音数据&#xff0c;并实时展示音波图&#xff1a; import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animation import pyaudio import wave import os import op…

【改进YOLOV8】融合动态蛇形卷积&DCNV2的草莓分级分割分割系统

1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 研究背景与意义 随着计算机视觉技术的不断发展&#xff0c;图像分割成为了一个重要的研究领域。图像分割可以将图像中的不同对象或区域进行分离&#xff0c;从而更好地理解图像内…

后端部署-阿里云服务器-开设端口-域名解析-安全证书-备案

本文以阿里云的轻量级数据库为例子。 前言 要搭建一个完整的后端系统一般的步骤&#xff1a; 获得一台服务器----->开设端口----->搭建后台所需要的语言和应用---->利用公网ip地址测试后端程序------->购买域名和证书-------->域名绑定和解析------->icp备…

SpringBoot——嵌入式 Servlet容器

一、如何定制和修改Servlet容器的相关配置 前言&#xff1a; SpringBoot在Web环境下&#xff0c;默认使用的是Tomact作为嵌入式的Servlet容器&#xff1b; 【1】修改和server相关的配置&#xff08;ServerProperties实现了EmbeddedServletContainerCustomizer&#xff09;例如…

C语言小游戏:三子棋

目录 &#x1f30d;前言 &#x1f685;目录设计 &#x1f48e;游戏逻辑设置 ⚔三子棋棋盘设计 ⚔三子棋运行逻辑 &#x1f440;怎么设置人下棋 &#x1f440;怎么设置电脑下棋 ✈如何判断输赢 ✍结语 &#x1f30d;前言 Hello,csdn的各位小伙伴你们好啊!这次小赵给大…

利用DateFormat、Date、Calendar等相关类,编程实现如下功能

&#xff08;1&#xff09;用户输入2个日期&#xff0c;第一个日期用整数形式输入&#xff0c;把输入的整数设置为日历对象1的年月日的值。第二个日期以字符串形式输入&#xff0c;形如“2022-10-25”&#xff0c;并设置为日历对象2的年月日的值。将2个日期以“xx年xx月xx日”的…

C++12.4

沙发床的多继承 多继承代码实现沙发床沙发床继承于沙发和床 代码&#xff1a; #include <iostream>using namespace std;//封装 沙发 类 class Sofa { private:string sitting;double *size; public://无参构造函数Sofa() {cout << "Sofa::无参构造函数&quo…

接口自动化测试用例

1、接口文档 根据开发、产品的接口文档&#xff0c;以及评审&#xff0c;进行设计接口测试用例&#xff0c;它不像UI测试&#xff0c;有个界面&#xff0c;对于简单的系统&#xff0c;需求文档不提供也能覆盖所有功能&#xff0c;接口测试虽说可以抓包&#xff0c;但抓包无法覆…

STM32串口接收不定长数据(空闲中断+DMA)

玩转 STM32 单片机&#xff0c;肯定离不开串口。串口使用一个称为串行通信协议的协议来管理数据传输&#xff0c;该协议在数据传输期间控制数据流&#xff0c;包括数据位数、波特率、校验位和停止位等。由于串口简单易用&#xff0c;在各种产品交互中都有广泛应用。 但在使用串…

HDFS客户端及API操作实验

实验二 HDFS客户端及API操作 实验目的&#xff1a; 1.掌握HDFS的客户端操作&#xff0c;包括上传文件、下载文件、重命名、查看目录等&#xff1b; 2.掌握HDFS的Java API使用&#xff0c;能够利用Java API实现上传、下载等常用操作&#xff1b; 实验内容&#xff1a; HDF…

深度学习——第3章 Python程序设计语言(3.3 Python数据类型)

3.3 Python数据类型 目录 1. Python数值数据类型 2. Python库的导入和使用 3. Python序列数据类型 4. Python组合数据类型 计算机能处理各种类型的数据&#xff0c;包括数值、文本等&#xff0c;不同的数据属于不同的数据类型&#xff0c;有不同的存储方式&#xff0c;支持…

EM32DX-C2【C#】

1说明&#xff1a; 分布式io&#xff0c;CAN总线&#xff0c;C#上位机二次开发&#xff08;usb转CAN模块&#xff09; 2DI&#xff1a; 公共端是&#xff1a; 0V【GND】 X0~X15&#xff1a;自带24v 寄存器地址&#xff1a;0x6100-01 6100H DI输入寄存器 16-bit &#x…

nginx部署和安装-后端程序多端口访问-后端代理设置

部分补充 查看nginx是否安装http_ssl_module模块 ./nginx -V 看到有 configure arguments: --with-http_ssl_module, 则已安装。 如果没有安装&#xff1a;参考文档 nginx官网地址&#xff1a;nginx: download 这里下载nginx-1.18.0稳定版tar.gz 下载后&#xff0c;利用…

2023年多元统计分析期末试题

一、简答题 1、试述距离判别法、Fisher判别法和贝叶斯判别法的异同。 二、 2、设 X {X} X~ N 2 {N_2} N2​(μ&#xff0c;Σ)&#xff0c;其中 X {X} X ~ ( X 1 {X_1} X1​, X 2 {X_2} X2​, X 3 {X_3} X3​)&#xff0c;μ ( μ 1 {μ_1} μ1​&#xff0c; μ 2 {μ_2} …

长度最小的子数组

长度最小的子数组 描述 : 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其总和大于等于 target 的长度最小的 连续子数组 [numsl, numsl1, …, numsr-1, numsr] &#xff0c;并返回其长度。如果不存在符合条件的子数组&#xff0c;返回 0 。 题目…

MySQL表的查询、更新、删除

查询 全列查询 指定列查询 查询字段并添加自定义表达式 自定义表达式重命名 查询指定列并去重 select distinct 列名 from 表名 where条件 查询列数据为null的 null与 (空串)是不同的&#xff01; 附&#xff1a;一般null不参与查询。 查询列数据不为null的 查询某列数据指定…

GPT市场将取代插件商店 openAI已经关闭plugins申请,全部集成到GPTs(Actions)来连接现实世界,可以与物理世界互动了。

Actions使用了plugins的许多核心思想&#xff0c;也增加了新的特性。 ChatGPT的"Actions"与"Plugins"是OpenAI在GPT模型中引入的两种不同的功能扩展机制。这两种机制的目的是增强模型的功能&#xff0c;使其能够处理更多样化的任务和请求。下面是对两者的比…

快手视频如何去掉水印?三个简单好用视频去水印方法

快手视频如何去掉水印&#xff1f;尽管新兴的短视频平台如春笋般涌现&#xff0c;吸引了众多观众在业余时间浏览和分享视频&#xff0c;快手作为当下主流短视频之一&#xff0c;许多自媒体创作者也常常会下载一些热门的视频素材进行二次编辑。然而&#xff0c;他们都可能会面临…