“双指针”算法上篇

devtools/2024/12/22 18:03:37/

『 你 的 名 字 』高帧4K动漫素材,无水印,需要自取!


题目:
一· 移动零
1.题目链接:移动零

2. 分析

解法一:暴力求解

就是新开一个数组,大小与原数组大小一致,只要不是数字0就进行写入,若是数字0,统计出现的

次数,最后把所有非0元素写入之后,在写入0元素。

对于一些没有思路的,老铁,刚刚看到此题,或许都会这样

但是,题目要求空间复杂度必须是O(N),所以这个想法就 “pass ” 掉了。

 解法二:双指针算法

3. 原理

双指针:注意这里可不是真正意义上的指针:int*,char* ,float* …… 而是指向元素的下标

cur 指针:指向当前要扫描的元素

dest指针:指向已经被扫描过的元素

初始位置:dest  = 0; cur = 0 (表示从左向右依次进行判断是否为数字0)

 cur 指向元素为0,则++cur

cur 指向元素非0,交换 cur,dest对应位置的元素,同时++cur,++dest

 

 这里建议,咱还是先根据自己的理解,来编写程序,看看自己上手能力咋样哈~~~

 

4.OJ代码
class Solution {
public:void moveZeroes(vector<int>& nums){int dest = 0,cur = 0;int n = nums.size();for(;cur < n;++cur){if(nums[cur] ){swap(nums[dest++],nums[cur]);}}}
};
二· 复写零
1.题目链接:复写零

2. 分析

解法一:暴力求解

还是老样子:新开一个数组,对于非0元素进行“复写”一遍,0元素,“复写” 两遍,可以解决问题,

但是不符合要求:必须原地修改数组(也就是说时间 复杂度 O(N))

解法二:双指针

模拟“异地”元素的移动:开一个与原始数组大小一样 的空间,对于非0元素进行“复写”一遍,0元

素,“复写” 两遍,我们可以找到新数组的最后一个元素,

假设我们知道“复写”之后的数组的最后一个元素,这个问题就简化了许多。此时就是对元素进行“复

写”的问题了:从前往后还是从后往前进行写入???

误区一:从前往后遍历

定义2个指针:cur = 0,dest = 0;

当cur 指向非0元素,arr[dest ]  = arr [ cur ] ,++dest,++cur

当cur 指向0元素:arr[dest ]  = arr [ cur ] ,++dest,  arr[dest ]  = arr [ cur ] ,++dest,++cur

 这样势必会造成数据覆盖,

所以说应该从后往前进行写入。

问题又来了:如何找到数组写入之后的最后一个元素呢?还是借助双指针

3. 原理

1)先模拟找到需写入数组的最后一个元素

图解:

双指针: dest = -1,cur = 0,cur 对应元素0,dest += 2,++cur 

注意:避免dest 越界,所以一个判读dest 是否 越界 dest >= n-1 

cur 对应非0元素:++dest,++cur

 结束之后:cur 位置对应的一定是写入数组的最后一个元素的位置

注意:结束之后dest 可能不是数组的有效位置

当cur 对应位置是元素0,会导致dest 越界,此时应该在dest 原有位置 前移动 2步,同时把最后一

个位置写入0即可

对于这个问题:可能会说直接让  dest = n-1 ,不就完了吗,反正最后dest  也是从数组的最后一个

位置开始“复写”

但是:可能恰好,cur 对应位置是元素0,写入数组的时候,就还只有一个位置,如果只是简单的

让dest = n- 1 ,对于这个临界情况就搞不了

临界情况判断:

 if (arr[cur] == 0 && dest > n-1)//注意这里后面的dest 的判断必须加上;也有可能复写的最后一个元素是0同时dest向后移动,刚刚到了n-1对应位置{arr[n - 1] = 0;dest -= 2;//注意永远指向下一个要填写的位置--cur;}
4.OJ代码
class Solution {
public:void duplicateZeros(vector<int>& arr)
{// 1:需要找到新数组最后一个元素,以方便复写从哪里开始int cur = 0, dest = -1;int n = arr.size();while (cur <= n - 1){if (arr[cur] != 0){++dest;}else{dest += 2;}if (dest >= n - 1){//对dest 需要判断是否越界break;}++cur;}//cur 一定是复写元素的最后一个,同时dest 永远指向的是要复写下一个元素位置// // 2:临界判断:可能结束的时候恰好cur遍历到原始数组元素为0//导致dest 越界//注意不能简单的让dest = n-1 ,这样就可能存在数据覆盖if (arr[cur] == 0 && dest > n-1)//注意这里后面的dest 的判断必须加上;也有可能复写的最后一个元素是0同时dest向后移动,刚刚到了n-1对应位置{arr[n - 1] = 0;dest -= 2;//注意永远指向下一个要填写的位置--cur;}// 3: 双指针:从后往前进行复写while (cur >= 0){if (arr[cur]){arr[dest--] = arr[cur--];}else{arr[dest--] = arr[cur];arr[dest--] = arr[cur--];}}}
};
三· 快乐数
1.题目链接:快乐数

2. 分析

对于数字n  ,就是拿到每一位的数字,并把每一位数字的平方进行相加求得平方之和,一直重复这

个过程,当变为1,就是快乐数,否则就不是快乐数。

 通过画图我们知道,对于一个数字是快乐数也好,不是快乐数也好,最终都会进入一个环,此时

问题就变成了判断是否为数字1 了。

不知道到这里,是否想起链表里面的一个OJ题目:判断链表是否有环?

对于这个题目感到陌生的友友们,可以看看之前我写的这个题解:判断链表是否有环

 所以对于这个问题的思路:快慢指针

3. 原理

定义2个指针:

slow 指针初始位置指向 n 所得的数字平方之和

fast 指针 初始位置指向 :slow 指针初始位置指向 n 所得的数字平方之和的平方之和

最终2指针一定相遇,所以就只需要判断其中一个指针是否为1即可

4.OJ代码
class Solution {//求当前数字每一位的平方和int num_sum(int n){int sum = 0;while(n){int x = n%10;sum += (x*x);n /= 10;}return sum;}
public:bool isHappy(int n){//题型:判断链表是否有环//快慢指针(也不一定就是指针)int slow = n;int fast = num_sum(n);while(fast != slow){//fast 走2步//slow 走1步slow = num_sum(slow);fast = (num_sum(num_sum(fast)));}return fast == 1;}
};

总结:

对于快慢指针这一思想的应用关键在于:初始位置下标的确定;如何迭代;还是需要注意一些临界

情况判断以及特例


http://www.ppmy.cn/devtools/97882.html

相关文章

(四)Flink Transformation 数据转换

用户通过算子能将一个或多个 DataStream 转换成新的 DataStream,在应用程序中可以将多个数据转换算子合并成一个复杂的数据流拓扑。 这部分内容将描述 Flink DataStream API 中基本的数据转换 API。 目录 Map(DataStream → DataStream) FlatMap(DataStream → DataStre…

【前端面试】javascript全栈开发——深挖nestJS项目

注意区别于nextJS框架——web全栈应用框架。 NestJS NestJS 是一个现代的、用于构建可扩展的 Node.js 服务器端应用程序的框架,它使用 TypeScript 构建,结合了 OOP、FP 和 FRP (详见下面)。 NestJS 提供了一个开箱即用的应用架构,允许开发者和团队创建高度可测试、可扩展、…

Compose(11)APT阶段的任务

在 Android 开发中&#xff0c;使用 Jetpack Compose 的声明式 UI 在编译的 APT&#xff08;Annotation Processing Tool&#xff0c;注解处理工具&#xff09;阶段可能会进行以下一些操作&#xff1a; 一、生成代码 可组合函数分析&#xff1a; APT 可以分析开发者编写的可组…

代理模式:静态代理和动态代理

目录 一、静态代理 1、优点 2、 缺点 3、示例 二、动态代理 1、优点 2、 缺点 3、示例 三、总结 在Java中&#xff0c;代理模式是一种结构型设计模式&#xff0c;它允许你在不改变目标对象代码的情况下&#xff0c;为目标对象提供一个代理对象&#xff0c;用以控制访问和增强功…

别再无效清理微信内存啦,这才是正确清理内存的方式

微信作为我们日常生活中必不可少的社交工具&#xff0c;随着时间的积累&#xff0c;往往会占据手机大量宝贵的存储空间。 如何在保证重要信息不丢失的同时&#xff0c;有效地管理和清理微信中的垃圾文件和无用数据&#xff0c;成为了一个值得探讨的话题。 本文将从几个方面介…

yum小bug

这个错误是在克隆的机子上安装mysql时&#xff0c;查看有无mysql发现的 [rootwebserve-2 backup] # yum list installed | grep mysql Repository cr is listed more than once in the configuration Repository fasttrack is listed more than once in the configuration 这…

HarmonyOs透明弹窗(选择照片弹窗样式)

1.鸿蒙中需要实现一个如下图的弹窗 2.由上图中可以得出&#xff0c;只需要三个Text组件依次向下排列&#xff0c;弹窗背景设置透明即可&#xff0c;弹窗代码如下(仅展示弹窗样式)&#xff1a; /**** 自定义选择图片弹窗** 外部定义需要导出*/ CustomDialog //自定义弹窗 export…

[数据集][目标检测]机械常用工具检测数据集VOC+YOLO格式4713张8类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;4713 标注数量(xml文件个数)&#xff1a;4713 标注数量(txt文件个数)&#xff1a;4713 标注…