当前位置: 首页 > news >正文

【专题刷题】双指针(一)

📝前言说明:

  • 本专栏主要记录本人的基础算法学习以及LeetCode刷题记录,按专题划分
  • 每题主要记录:1,本人解法 + 本人屎山代码;2,优质解法 + 优质代码;3,精益求精,更好的解法和独特的思想(如果有的话)
  • 文章中的理解仅为个人理解。如有错误,感谢纠错

🎬个人简介:努力学习ing
📋本专栏:C++刷题专栏
📋其他专栏:C语言入门基础,python入门基础,C++学习笔记,Linux
🎀CSDN主页 愚润泽

视频

  • 293. 移动零
    • 个人解
    • 优质解
  • 1089. 复写零
    • 个人解
    • 优质解:

293. 移动零

在这里插入图片描述


个人解

思路:请添加图片描述
用时:15:16,(真是没救了,写成这样)
屎山代码:通过

class Solution {
public:void moveZeroes(vector<int>& nums) {int n = nums.size();int slow = 0;int fast = 1;while(slow < n && fast < n){while(slow < n && nums[slow] != 0){slow++;}while(fast < n && (fast < slow || nums[fast] == 0)){fast++;}if(slow < n && fast < n){swap(nums[slow], nums[fast]);slow++;fast++;}}}
};

时间复杂度:O(n)
空间复杂度:O(1)


优质解

思路:整个数组可以划分成:已排序区[0, slow] + 零区[ slow + 1, fast ) + 待排序区[fast, n-1]
我屎山代码的问题:我的slowfast是分别移动的,后续还需要自己维护fast > slow
优质解法:

  • slow指针始终指向已排序区的最后一个元素,slow不主动移动,只在交换时移动,这样就可以始终用来标识已排序区的位置。
  • fast指针遍历数组,当fast != 0时,和slow + 1位置的0交换。
class Solution {
public:void moveZeroes(vector<int>& nums) {int slow = -1, fast = 0;for(fast = 0; fast < nums.size(); fast++){if(nums[fast]){swap(nums[fast], nums[slow + 1]);slow++;}}}
};

时间复杂度:O(n)
空间复杂度:O(1)


1089. 复写零

在这里插入图片描述

个人解

思路:一个指针在前,一个指针在后,前指针遇到0要复写的时候,通过后指针,把复写位置后的元素都往后移动一位,腾出空间。

用时:17:21
屎山代码:通过

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

时间复杂度:O( n 2 n^2 n2)
空间复杂度:O(1)


优质解:

首先,我们先思考,如果不是就地操作的解法:
创建一个新的数组,然后一个指针cur指向原数组,一个指针dest指向新数组,dest根据cur的值不断进行复写操作。

那换成就地操作呢?
如果直接这么操作,那dest复写两次的时候就会覆盖还没有复写的值。

那能不能从后往前进行复写操作?
答案是可以的,问题是要先找到最后一个复写的数。

最后一个复写的数由什么决定?
如果我们看题不仔细,不认真思考的话就会简单认为:0的个数直接决定后面几个数会被移出数组外,如:若有3个0,那么倒数第4个数就是最后一个复写的数。(因为后3个数的位置 → 被前面复写的0个替代了)
但其实不然,因为:0有可能被移动出去

所以,重点又变成了,如何找最后一个要复写的数的位置。
方法:我们先模拟一遍复写的过程但是不复写,就可以让cur定位到最后一个要复写的元素,dest指向从后往前复写的第一个要复写的开始位置。
步骤:

  1. cur指向当前要复写的元素,遍历数组,dest指向已经复写完的位置(的最后一个)
  2. arr[cur] == 0dest移动两步,否则为一步
  3. 判断dest是否到达结束位置,达到了就提前退出循环。
    注意点1:在本次循环中的cur不能移动,因为cur指向的是要复写的,如果移动了就到了下一个没有复写的位置。
    注意点2:会有在数组外复写的情况:这种情况是在dest == n-1的时候还要复写两个0,解决方法:只需要让arr[n-1] = 0dest -= 2cur -= 1就行,因为这种情况下已确定最后一位写的是0

文字叙述晦涩难懂,建议画图

代码:

class Solution {
public:void duplicateZeros(vector<int>& arr) {int cur = 0, dest = -1, n = arr.size(); // dest指向复写完的最后一个位置while(cur < n) {if(arr[cur]) dest++; else dest += 2;if(dest >= n-1) break; // dest = n-1 代表已经写完最后一个位置了cur++; // cur指向的元素代表要复写的元素}if(dest == n) // 代表在数组外面写了{arr[n-1] = 0;dest -= 2;cur -= 1;}while(cur >= 0){if(arr[cur]) arr[dest--] = arr[cur--];else{arr[dest--] = 0;arr[dest--] = 0;cur--;}}}
};

时间复杂度:O(n)
空间复杂度:O(1)

🌈我的分享也就到此结束啦🌈
要是我的分享也能对你的学习起到帮助,那简直是太酷啦!
若有不足,还请大家多多指正,我们一起学习交流!
📢公主,王子:点赞👍→收藏⭐→关注🔍
感谢大家的观看和支持!祝大家都能得偿所愿,天天开心!!!

相关文章:

  • 静态站点生成
  • 解决USG5150防火墙web无法连接问题
  • 【AI论文】PixelFlow:基于流的像素空间生成模型
  • 【android bluetooth 协议分析 21】【ble 介绍 1】【什么是RPA】
  • DDS信号发生器设计
  • 自编码网络深度解析:原理、数学推导与实现细节
  • 标易行项目redis内存中放哪些数据
  • linux多线(进)程编程——(7)消息队列
  • 熟悉Linux下的编程
  • MySQL分组查询和子查询
  • secsgem v0.3.0版本使用说明文档
  • 探索 C 与 Java/Kotlin 的语言差异:从指针到高阶函数
  • 深入定制 QSlider——实现精准点击跳转与拖拽区分
  • 用Python手搓一个简单的饭店管理系统(上篇)
  • 依赖注入(DI)与自动装配的深度分析:优势、局限与实践考量
  • 智慧城市:如同为城市装上智能大脑,开启智慧生活
  • 用 Depcheck 去除Vue项目没有用到的依赖
  • GitHub action中的 jq 是什么? 常用方法有哪些
  • 计算机保研机试准备——C++算法题
  • 【cmake-笔记】
  • 特写|为何这么多人喜欢上海半马,答案藏在他们的笑容里
  • 五一出境游火爆:境外包车订单增长25%,日本酒店价格贵了好几倍
  • 云南省交通发展投资有限责任公司原党委书记、董事长陈以东接受审查调查
  • 中国足协、中足联:对中超浙江队外援阿隆·布彭扎不幸离世表示深切哀悼
  • 遇见古籍里的先贤,山西博物院“晋国垂棘”明日开展
  • 黄仁勋时隔3个月再次到访北京