【经典算法】LeetCode 283. 移动零(Java/C/Python3/Go实现含注释说明,Easy)

简介: 【经典算法】LeetCode 283. 移动零(Java/C/Python3/Go实现含注释说明,Easy)
  • 作者简介:阿里非典型程序员一枚 ,记录在大厂的打怪升级之路。 一起学习Java、大数据、数据结构算法(公众号同名
  • ❤️觉得文章还不错的话欢迎大家点赞👍➕收藏⭐️➕评论,💬支持博主,记得点个大大的关注,持续更新🤞
    ————————————————-

移动零

  • 标签(题目类型):数组,双指针

题目描述

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

示例:

输入: [0,1,0,3,12]

输出: [1,3,12,0,0]

说明:

必须在原数组上操作,不能拷贝额外的数组。

尽量减少操作次数。

原题:283. 移动零

思路及实现

方式一:双指针

思路

使用两个指针 iji 用于遍历数组,j 用于指向非零元素应该存放的位置。遍历数组时,如果当前元素不为零,则将其交换到 j 的位置,并将 j 后移一位。这样,遍历结束后,所有非零元素都移动到了数组的前面,而后面的位置都是零。

代码实现

Java版本
public void moveZeroes(int[] nums) {
    int j = 0; // 指向非零元素应该存放的位置
    for (int i = 0; i < nums.length; i++) {
        if (nums[i] != 0) {
            // 如果当前元素不为零,则交换到 j 的位置,并将 j 后移一位
            int temp = nums[i];
            nums[i] = nums[j];
            nums[j] = temp;
            j++;
        }
    }
}

说明:

  • 变量 j 初始化为0,表示非零元素应该存放的起始位置。
  • 遍历数组 nums,如果当前元素不为零,则与 nums[j] 交换位置,并将 j 后移一位。
  • 遍历结束后,所有非零元素都移动到了数组的前面,后面的位置都是零。
C语言版本
void moveZeroes(int* nums, int numsSize) {
    int j = 0; // 指向非零元素应该存放的位置
    for (int i = 0; i < numsSize; i++) {
        if (nums[i] != 0) {
            // 如果当前元素不为零,则交换到 j 的位置,并将 j 后移一位
            int temp = nums[i];
            nums[i] = nums[j];
            nums[j] = temp;
            j++;
        }
    }
}

说明:

  • 与Java版本类似,使用 j 指针来记录非零元素应该存放的位置。
  • 交换非零元素到 j 的位置,并更新 j 的值。
Python3版本
def moveZeroes(nums):
    j = 0  # 指向非零元素应该存放的位置
    for i in range(len(nums)):
        if nums[i] != 0:
            # 如果当前元素不为零,则交换到 j 的位置,并将 j 后移一位
            nums[i], nums[j] = nums[j], nums[i]
            j += 1

说明:

  • 使用Python的简洁语法,直接交换元素的位置。
  • 变量 j 的作用和逻辑与Java和C版本相同。
Golang版本
func moveZeroes(nums []int) {
    j := 0 // 指向非零元素应该存放的位置
    for i := 0; i < len(nums); i++ {
        if nums[i] != 0 {
            // 如果当前元素不为零,则交换到 j 的位置,并将 j 后移一位
            nums[i], nums[j] = nums[j], nums[i]
            j++
        }
    }
}

说明:

  • Golang的实现逻辑与Java和C类似,通过 j 指针来记录非零元素应该存放的位置。
  • 交换元素时,使用Golang的多返回值赋值特性。

复杂度分析

  • 时间复杂度:O(n),其中 n 是数组的长度。只需要遍历数组一次。
  • 空间复杂度:O(1)。只使用了常数级别的额外空间。

方式二:计数法

思路

首先遍历数组,统计非零元素的个数。然后再次遍历数组,将非零元素按顺序放到数组的前面,其余位置填充为零。

代码实现

Java版本
public void moveZeroes(int[] nums) {
    int count = 0; // 统计非零元素的个数
    for (int num : nums) {
        if (num != 0) {
            count++;
        }
    }
    
    int index = 0; // 非零元素应该存放的位置索引
    for (int num : nums) {
        if (num != 0) {
            nums[index] = num; // 将非零元素按顺序放到数组的前面
            index++;
        }
    }
    
    // 将剩余位置填充为零
    while (index < nums.length) {
        nums[index] = 0;
        index++;
    }
}

说明:

  • 第一次遍历数组,统计非零元素的个数。
  • 第二次遍历数组,将非零元素按顺序放到数组的前面。
  • 最后,将剩余的位置填充为零。
C语言版本
void moveZeroes(int* nums, int numsSize) {
    int count = 0; // 统计非零元素的个数
    for (int i = 0; i < numsSize; i++) {
        if (nums[i] != 0) {
            count++;
        }
    }
    
    int index = 0; // 非零元素应该存放的位置索引
    for (int i = 0; i < numsSize; i++) {
        if (nums[i] != 0) {
            nums[index] = nums[i]; // 将非零元素按顺序放到数组的前面
            index++;
        }
    }
    
    // 将剩余位置填充为零
    while (index < numsSize) {
        nums[index] = 0;
        index++;
    }
}

说明:

  • 与Java版本类似,使用两次遍历,第一次统计非零元素个数,第二次将非零元素按顺序放到数组前面,并将剩余位置填充为零。
Python3版本
def moveZeroes(nums):
    count = sum(1 for num in nums if num != 0) # 统计非零元素的个数
    index = 0 # 非零元素应该存放的位置索引
    for num in nums:
        if num != 0:
            nums[index] = num # 将非零元素按顺序放到数组的前面
            index += 1
    
    # 将剩余位置填充为零
    while index < len(nums):
        nums[index] = 0
        index += 1

说明:

  • 使用Python的简洁语法和特性来实现计数和填充操作。
Golang版本
func moveZeroes(nums []int) {
    count := 0 // 统计非零元素的个数
    for _, num := range nums {
        if num != 0 {
            count++
        }
    }
    
    index := 0 // 非零元素应该存放的位置索引
    for _, num := range nums {
        if num != 0 {
            nums[index] = num // 将非零元素按顺序放到数组的前面
            index++
        }
    }
    
    // 将剩余位置填充为零
    for i := index; i < len(nums); i++ {
        nums[i] = 0
    }
}

说明:

  • Golang版本的实现逻辑与其他语言版本类似,通过两次遍历来实现移动零元素。

复杂度分析

  • 时间复杂度:O(n),其中 n 是数组的长度。需要遍历数组两次。
  • 空间复杂度:O(1)。只使用了常数级别的额外空间。

总结

方式 优点 缺点 时间复杂度 空间复杂度
方式一(双指针) 代码简洁,易于理解 无明显缺点 O(n) O(1)
方式二(计数法) 逻辑清晰,易于实现 需要遍历数组两次 O(n) O(1)

相似题目

相似题目 难度 链接
leetcode 27 简单 力扣27
leetcode 28 简单 力扣28

欢迎一键三连(关注+点赞+收藏),技术的路上一起加油!!!代码改变世界

  • 关于我:阿里非典型程序员一枚 ,记录在大厂的打怪升级之路。 一起学习Java、大数据、数据结构算法公众号同名),回复暗号,更能获取学习秘籍和书籍等
相关文章
|
2月前
|
人工智能 安全 Java
Java和Python在企业中的应用情况
Java和Python在企业中的应用情况
83 7
|
3月前
|
数据采集 缓存 Java
Python vs Java:爬虫任务中的效率比较
Python vs Java:爬虫任务中的效率比较
|
2月前
|
Java 程序员 开发工具
在比较Java和Python哪个更易学
在比较Java和Python哪个更易学
45 4
|
2月前
|
Java 程序员 Python
Java和Python
Java和Python
29 2
|
4月前
|
Java Linux Python
Linux环境下 代码java调用python出错
Linux环境下 代码java调用python出错
82 4
|
3月前
|
Java Python
如何通过Java程序调用python脚本
如何通过Java程序调用python脚本
53 0
|
3月前
|
安全 Java Python
基于python-django的Java网站全站漏洞检测系统
基于python-django的Java网站全站漏洞检测系统
45 0
|
Java 测试技术 Go
拼不过 GO?阿里如何重塑云上的 Java
Java 诞生于20年前,拥有大量优秀的企业级框架,践行 OOP 理念,更多体现的是严谨以及在长时间运行条件下的稳定性和高性能。反观如今,在要求快速迭代交付的云场景下,语言的简单性似乎成了首要的要求,而传统的 Java 语言显得有一些过于重量了。今天,阿里 JVM 团队技术专家郁磊(花名:梁希)分享 JVM 团队是如何面对和处理集团巨大的业务规模和复杂的业务场景的。
19738 0
拼不过 GO?阿里如何重塑云上的 Java
|
Cloud Native Java 测试技术
拼不过 GO?阿里如何重塑云上的 Java
Java 诞生于20年前,拥有大量优秀的企业级框架,践行 OOP 理念,更多体现的是严谨以及在长时间运行条件下的稳定性和高性能。反观如今,在要求快速迭代交付的云场景下,语言的简单性似乎成了首要的要求,而传统的 Java 语言显得有一些过于重量了。今天,阿里 JVM 团队技术专家郁磊(花名:梁希)分享 JVM 团队是如何面对和处理集团巨大的业务规模和复杂的业务场景的。
2713 0
拼不过 GO?阿里如何重塑云上的 Java
|
13天前
|
监控 Java
java异步判断线程池所有任务是否执行完
通过上述步骤,您可以在Java中实现异步判断线程池所有任务是否执行完毕。这种方法使用了 `CompletionService`来监控任务的完成情况,并通过一个独立线程异步检查所有任务的执行状态。这种设计不仅简洁高效,还能确保在大量任务处理时程序的稳定性和可维护性。希望本文能为您的开发工作提供实用的指导和帮助。
65 17