双指针 — 移动零

目录

[1. 题目解析](#1. 题目解析)

[2. 算法讲解](#2. 算法讲解)

[3. 编写代码](#3. 编写代码)


1. 题目解析

283. 移动零

移动0的题型是为数组划分,或者数组分块。

这类题的特点是给我们一个数组,再制定一个规则,让我们在这个规则下,把数组划分成不同的区间:

这个题的标准是:

在原数组的基础上,把所有非0元素划分到数组的左边,所有0元素分配到数组的右边 。

这样,所有数组元素就被划分成两个区间:

解决这个题目,我们用一种非常经典的算法,就是双指针算法(利用数组下标充当指针)


2. 算法讲解

双指针算法:我们定义两个指针 dest ,cur

这两个指针从左往右遍历数组的时候,会把整个数组划分为三个区间:

我们先不管这些区间,先来介绍这两个指针的作用:

cur :从左往右扫描数组,遍历数组

dest:已处理的区间内,非零元素的最后一个位置

这时候,cur会把整个数组划分成两个区间,**左边为已经处理的区间,右边为未处理的区间,**怎么处理的我们先不管;

dest指针起到分割线的作用,将cur左边已经处理过的区间又细分成两个小区间。

这里又有一个小问题:为什么第二个区间是到cur-1呢?

这又回到cur指针本身的含义上,cur这个指针用于从左往右扫描数组,而这三个区间分别代表不同的含义:

当cur走到n下标,就说明这个数组已经全部扫描完成。这时候,数组就被 dest 划分成两部分;也就是刚刚三个区间,只剩下前面两个区间,其中,左边部分是非0元素,右边部分是0元素。

那么接下来,我们要做的就是,让这两个指针从左往右扫码数组的过程中,保持两个指针划分的三个区间的性质。


以这个图的数组为例子:

cur刚开始初始化为这个数组的0下标位置;

对于 dest 指针,它表示非0元素的最后一个位置,刚开始扫描数组的时候,并没有非0元素;所以 刚开始让dest指向数组-1下标的位置。


刚开始dest先不动,因为cur是扫描数组的,所以先让cur先动。cur从前往后移动的过程中,会出现两种情况,遍历的元素是否为0:

当cur遇到0元素时,我们要保证 非0 0 未扫描 这三个区间的性质不变:

刚开始,cur指向0下标的数组元素,值为0 ;

在cur遇到0元素时,如cur当前遍历的0下标元素0。我们仅需要让cur向后移动一位即可。

cur向右移动一位,cur左边的区间dest+1,cur-1中,都是0元素。

所以cur在遍历到0元素,不做任何处理。


在cur遍历到非0元素时,我们让当前遍历的元素加入最左边的区间 0 ,dest

所以相当于 0,dest 这个区间中,多了一个元素,我们让dest往右移动一位:

移动好dest后,cur先不动,这时候交换cur和dest下标的元素:

所以cur当前遍历的元素,在交换后,相当于已经被处理过了,cur向后移动一位:


综上所述,如果cur遍历的元素是0元素,则不做任何处理;

如果cur遍历到非0元素时,0,dest区间就要多一个元素,所以让dest指针往后移动一位,cur先不动;

让dest指向的元素与cur指向的元素进行交换,cur++;以 cur<n 为循环终止条件。


3. 编写代码

对于这个题目,对cur指针的所有调整,都通过for循环完成,不用再在if语句中调整cur;

在cur遍历到0元素时,不做任何处理;所以,我们在for循环中,只要写cur遍历到非0元素的处理方法即可:

java 复制代码
class Solution {
    public void moveZeroes(int[] nums) {
        int dest = -1;

        for(int cur = 0;cur<nums.length;cur++){

            if(nums[cur]!=0){
                dest++;
                int tmp=nums[cur];
                nums[cur]=nums[dest];
                nums[dest]=tmp;
            }
        }
    }
}
相关推荐
学长毕设7 小时前
基于SpringBoot的实验室资产管理系统
java·spring boot·后端
zzu123zsw8 小时前
从臃肿的模板调用到声明式契约:深入 UniHttp 动态代理与多渠道生命周期扩展
java·spring boot·microsoft·unihttp
UIU1149 小时前
P1233 [ICPC 2001 Taejon R] 木棍加工
数据结构·c++·算法·动态规划
源码集结号9 小时前
云诊所门诊系统源码,基于SpringBoot+Vue.js架构,支持多租户设计与Docker容器化部署
java·spring boot·源码·医院信息系统·门诊系统·诊所系统
论文复现现场9 小时前
WRF、FEA 能用 L40S 加速吗?求解器检查、断点恢复与长期运行
java·数据库·算法·wrf·有限元分析·gpu计算·断点续算
ZhengEnCi9 小时前
用 AI 写代码为什么拼到最后还是拼人:算力瓶颈与领域专家提示词的本质差异
算法·架构
啃瓜子的松鼠9 小时前
泛微OAe9-后端二开异步调用
java
秋天的怀念_David10 小时前
第二十一夜 · 数字黑洞与西西弗斯的惩罚
java·程序人生·算法
外收内放10 小时前
Python基础语法练习题(73)
java·前端·python
Wang's Blog10 小时前
Java 项目实战: 交友项目 - 环信后台发送消息测试
java·交友