2.LeetCode 1089. 复写零——双指针解法学习笔记

目录

一、题目解析

二、算法原理:双指针法

步骤1:找最后一个"复写"的数

步骤2:处理边界情况

步骤3:从后往前复写

三、代码实现(Java)

四、复杂度分析

五、总结


OJ链接:https://leetcode.cn/problems/duplicate-zeros/description/

今天学习了LeetCode第1089题《复写零》,这道题要求我们在++长度固定++ 的数组里,把每个0都复写一遍(也就是变成两个0),其他元素向右平移,而且不能超出数组长度。题目还强调要++就地修改,不返回新数组。下面我把思路理清楚~++

一、题目解析

先看题目描述:给定整数数组arr,将出现的每个0复写一遍(比如[1,0,2]变成[1,0,0,2]?但数组长度固定,所以超出的元素会被截断),其余元素右移。注意++不要越界写入,就地修改。++

举个例子:

  • 示例1:输入arr = [1,0,2,3,0,4,5,0],输出[1,0,0,2,3,0,0,4](因为最后一个0复写后超出长度,所以只保留前面的部分)。

  • 示例2:输入arr = [1,2,3],输出[1,2,3](没有0,所以不变)。

二、算法原理:双指针法

笔记里说,先想"异地"操作(比如新建一个数组来放结果),再优化成"就地"的双指针操作。++核心是找到最后一个需要复写的0的位置,然后从后往前填充。++

步骤1:找最后一个"复写"的数

用两个指针:cur(遍历原数组)和dest(记录复写后的位置)。

  • 如果arr[cur]是0,dest加2(因为0要复写,占两个位置);

  • 如果arr[cur]不是0,dest加1(占一个位置);

  • dest超过或等于数组长度n-1时,停止(说明找到最后一个需要复写的数了)。

步骤2:处理边界情况

如果dest刚好等于n(比如数组最后一个元素是0,复写后dest会到n),这时候要把最后一个位置设为0,然后curdest回退(cur--dest -= 2)。

步骤3:从后往前复写

现在cur指向最后一个需要复写的数,dest指向结果数组的最后一个位置。从后往前遍历:

  • 如果arr[cur]不是0,就把arr[cur]放到dest位置,然后cur--dest--

  • 如果arr[cur]是0,就把0放到destdest-1位置(复写),然后cur--dest -= 2

三、代码实现(Java)

代码很清晰,看:

java 复制代码
class Solution {
    public void duplicateZeros(int[] arr) {
        int cur = 0, dest = -1, n = arr.length;
        
        // 1. 先找到最后一个需要复写的数
        while (cur < n) {
            if (arr[cur] == 0) {
                dest += 2;
            } else {
                dest += 1;
            }
            if (dest >= n - 1) {
                break;
            }
            cur++;
        }
        
        // 2. 处理边界情况(比如最后一个元素是0,复写后dest超了)
        if (dest == n) {
            arr[n - 1] = 0;
            cur--;
            dest -= 2;
        }
        
        // 3. 从后向前完成复写操作
        while (cur >= 0) {
            if (arr[cur] != 0) {
                arr[dest--] = arr[cur--];
            } else {
                arr[dest--] = 0;
                arr[dest--] = 0;
                cur--;
            }
        }
    }
}

四、复杂度分析

  • 时间复杂度:O(N),因为curdest都只遍历数组一次(最多两次,但总体是线性)。

  • 空间复杂度:O(1),就地修改,没有额外空间。

五、总结

这道题的关键是双指针找位置 +从后往前填充 。一开始可能会想新建数组,但题目限制了就地修改,所以用双指针先确定最后一个复写的数的位置,再从后往前填,避免了元素覆盖的问题。一定要手动模拟一遍过程,就能理解curdest的移动逻辑啦~

相关推荐
青山师1 小时前
Java枚举深度解析:从类型安全到JVM级单例模式
java·jvm·枚举·javase·java面试·java核心
雨辰AI1 小时前
SpringBoot3 + 人大金仓 V9 全栈日志实战:Logback + Loki + Filebeat 构建统一日志平台
java·数据库·后端·云原生·eureka·logback·政务
Struggle_97551 小时前
算法知识-数学
算法
超梦dasgg1 小时前
java微服务项目的架构和链路串联
java·微服务·架构
SamDeepThinking1 小时前
打造高效团队的四个关键动作
java·后端·团队管理
khalil10202 小时前
代码随想录算法训练营Day-41动态规划08 | 121. 买卖股票的最佳时机、122.买卖股票的最佳时机II、123.买卖股票的最佳时机III
数据结构·c++·算法·leetcode·动态规划
量子炒饭大师2 小时前
【优化算法:双指针算法刷题宝典】—— 三数之和
算法·优化算法·双指针·三数之和
1104.北光c°2 小时前
Leetcode215 三种写法完成数组中的第K个最大元素 【hot100算法个人笔记】【java写法】
java·笔记·程序人生·算法·leetcode·排序算法·快速选择
青山师2 小时前
Java注解深度解析:从元数据机制到框架开发基石
java·开发语言·注解·javase·java面试·后端开发·java核心