【双指针】破解数组的协奏曲一(移动零)
专栏前言:
 在学习算法的时候,我刷一些算法题可以从大语言模型得到答案,但记不住,所以出这个专栏来完成自己对算法题目的感悟。也希望大家能有所收获。
 
主要简介:
个人主页:爱装代码的小瓶子
算法专栏:你的算法难题小助手
cpp编程语言详解
操作系统详解–Linux

 
本文目录
- 1. 题目一:
- 0.开始的思路:
- 1.正确思路:
- 2.代码如下:
- 3.总结:
 
1. 题目一:
题目:283. 移动零
 
0.开始的思路:
题目标注是简单,但是我刚入手还是比较困难的。我一开始的想法也是双指针:
- 定义两个下标:一个dest(destination)和cur(current),一个是用来分割0和非0的,一个是用来遍历的数组的
- 但是我卡在的在什么的条件下进行交换: 
- 可以看到如果dest是0的话我来交换,这是完全错误的。所以我卡死了。
1.正确思路:
我的方式是不在看dest这个分界符,而是考虑cur这个下标,如果cur不是0,那么我们先让dest++,进入数组,或者讲进入分割区域前的最后一个元素。(比如cur = 0 ,那么就没有分割,dest = -1;如果cur = 2,那么dest = 1,它就是分割区域前的最后一个元素)在进行交换。注意:先++后交换。
 这样非0数字就进入了分割之前,而0则跑入cur的最后的位置,cur可以继续++。
2.代码如下:
class Solution {
public:void moveZeroes(vector<int>& nums) {for(int cur = 0,dest = -1;cur < nums.size();cur++){//cur指针是用来遍历数组的,dest指针是用来分割0和非0if(nums[cur]){swap(nums[cur],nums[++dest]);}}}
};
结果如下:
 
3.总结:
- 两个指针(下标) - cur是“侦察兵”,从数组开头向后遍历,检查每一个元素。
- dest是“已整理好的非零序列的末尾标记”。初始时为 -1,表示还没有非零元素被整理。
 
- 先++后交换”的过程: - 先让 dest++:这意味着 dest向右移动一位,指向了当前已整理的非零序列之后的位置(这个位置原本应该是0,或者是尚未处理的区域的开头)
- 然后交换 dest和 cur位置的元素:这个操作的效果是,将新发现的非零元素(在 cur位置)交换到已整理的非零序列的末尾(dest的新位置),同时把 dest原位置可能存在的0交换到了 cur的位置。
- 当 cur遇到零时:不做交换,仅 cur继续向后移动,这个零会被后续的非零元素“替换”到后面去。
 


