双指针 — 移动零

目录

[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;
            }
        }
    }
}
相关推荐
appearappear4 小时前
Mac 上重新安装了Cursor 2.2.30,重新配置 springboot 过程记录
java·spring boot·后端
CryptoRzz4 小时前
日本股票 API 对接实战指南(实时行情与 IPO 专题)
java·开发语言·python·区块链·maven
程序员水自流4 小时前
MySQL数据库自带系统数据库功能介绍
java·数据库·mysql·oracle
旧梦吟4 小时前
脚本网页 三人四字棋
前端·数据库·算法·css3·html5
谷哥的小弟4 小时前
Spring Framework源码解析——RequestContext
java·后端·spring·框架·源码
凯_kyle4 小时前
Python 算法竞赛 —— 基础篇(更新ing)
笔记·python·算法
天远Date Lab4 小时前
Java微服务实战:聚合型“全能小微企业报告”接口的调用与数据清洗
java·大数据·python·微服务
lizz314 小时前
C++操作符重载深度解析
java·c++·算法
武子康4 小时前
Java-205 RabbitMQ 工作模式实战:Work Queue 负载均衡 + fanout 发布订阅(手动ACK/QoS/临时队列)
java·性能优化·消息队列·系统架构·rabbitmq·java-rabbitmq·mq
CodeCraft Studio4 小时前
Vaadin 25 正式发布:回归标准Java Web,让企业级开发更简单、更高效
java·开发语言·前端·vaadin·java web 框架·纯java前端框架·企业级java ui框架