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

LeetCode题练习与总结:移动零--283

一、题目描述

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

示例 1:

输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]

示例 2:

输入: nums = [0]
输出: [0]

提示:

  • 1 <= nums.length <= 10^4
  • -2^31 <= nums[i] <= 2^31 - 1

二、解题思路

这个问题可以通过双指针的方法来解决。我们可以定义两个指针,一个指针(我们可以称之为lastNonZeroFoundAt)指向最后一个非零元素的索引,另一个指针(我们可以称之为cur)用于遍历数组。

遍历数组时,如果当前元素不为零,则将其与lastNonZeroFoundAt指向的元素交换,并将lastNonZeroFoundAt指针向前移动一位。这样可以保证所有非零元素都被移动到了数组的前面,且相对顺序不变。遍历结束后,所有在lastNonZeroFoundAt之后的位置都应该设置为0。

以下是具体的步骤:

  1. 初始化lastNonZeroFoundAt为0。
  2. 遍历数组,使用cur指针。
  3. 如果nums[cur]不为0,则交换nums[cur]nums[lastNonZeroFoundAt],并将lastNonZeroFoundAt向前移动一位。
  4. 继续遍历,直到cur到达数组末尾。
  5. lastNonZeroFoundAt到数组末尾的所有位置设置为0。

三、具体代码

class Solution {public void moveZeroes(int[] nums) {if (nums == null || nums.length == 0) return;int lastNonZeroFoundAt = 0;// 将所有非零元素移动到数组前面for (int cur = 0; cur < nums.length; cur++) {if (nums[cur] != 0) {// 交换当前非零元素与lastNonZeroFoundAt指向的元素int temp = nums[cur];nums[cur] = nums[lastNonZeroFoundAt];nums[lastNonZeroFoundAt] = temp;// 更新lastNonZeroFoundAtlastNonZeroFoundAt++;}}// 将lastNonZeroFoundAt之后的所有元素设置为0for (int i = lastNonZeroFoundAt; i < nums.length; i++) {nums[i] = 0;}}
}

这段代码实现了将所有0移动到数组末尾,并且保持了非零元素的相对顺序,同时没有使用额外的数组空间,满足了原地对数组进行操作的要求。

四、时间复杂度和空间复杂度

1. 时间复杂度
  • 遍历数组:代码中有一个for循环,用于遍历数组中的每个元素。这个循环会执行nums.length次,因此这部分的时间复杂度是O(n),其中n是数组的长度。

  • 交换操作:在遍历数组的过程中,每当遇到一个非零元素,就会执行一次交换操作。在最坏的情况下(即数组中所有元素都是非零的),这个操作也会执行nums.length次。交换操作是常数时间的,因此这部分的时间复杂度同样是O(n)。

  • 设置零操作:在遍历数组之后,有一个for循环用于将剩余的元素设置为0。在最坏的情况下(即数组中没有任何零),这个循环也会执行nums.length次。每次设置操作是常数时间的,因此这部分的时间复杂度也是O(n)。

由于以上三部分操作是顺序执行的,因此总的时间复杂度是这三个操作的累加,即O(n) + O(n) + O(n) = O(n)。

2. 空间复杂度
  • 临时变量:代码中使用了一个临时变量temp用于交换操作,这个变量占用了常数空间,因此空间复杂度是O(1)。

  • 辅助空间:除了输入数组之外,代码没有使用任何额外的数据结构(如数组、列表等)来存储数据,因此没有使用额外的空间。

综上所述,总的空间复杂度是O(1),即代码使用了常数额外空间。

五、总结知识点

  • 数组的操作

    • 数组元素的访问:通过索引直接访问数组元素。
    • 数组元素的赋值:直接给数组元素赋值。
  • 条件判断

    • if语句:用于判断数组元素是否为零。
    • nulllength属性检查:用于判断数组是否为空或长度为零。
  • 循环结构

    • for循环:用于遍历数组中的所有元素。
  • 指针/索引概念

    • 使用变量lastNonZeroFoundAt作为指针,指向数组中最后一个非零元素的索引位置。
    • 使用变量cur作为当前遍历的索引。
  • 交换操作

    • 使用临时变量temp来交换两个数组元素的值。
  • 算法思想

    • 双指针(或双索引)技术:通过两个指针来维护数组中非零元素的位置。
  • 原地算法

    • 原地修改数组,不使用额外的存储空间来保存结果。
  • 边界条件处理

    • 在函数开始时检查输入数组的边界条件,即是否为null或长度为零。

以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。


http://www.mrgr.cn/news/44589.html

相关文章:

  • 二维数组的旋转与翻转(C++)(上(这只是简单讲解))
  • 开源项目带来的思考
  • 修改 MySQL 数据库中的唯一键
  • Oracle登录报错-ORA-01017: invalid username/password;logon denied
  • 推荐一款强大的书签管理工具,让你的网址不在落灰
  • 汉诺塔问题
  • 2.4Mybatis——缓存机制
  • PyQt5技术详解:从基础到高级应用
  • 无人机单目+激光+IMU复杂弧形(隧道)退化场景SLAM技术详解
  • 缓存 = Buffer + Cache
  • 如何证明线段树的操作复杂度
  • 没有屋檐的房子-017
  • 什么是pip? -- Python 包管理工具
  • 高数面积公式推导过程
  • Cocos_鼠标滚轮放缩地图
  • 深入了解卡尔曼滤波:最优状态估计的数学神器
  • 2.1MyBatis——ORM对象关系映射
  • 整数划分问题
  • 智能工厂的软件设计 【三ji】公共逻辑语言映射到祖传代码( 元级)中为“Program”规划了三层置标架构,即“Program”的标准通用置标语言
  • 面试系列-淘天提前批面试