【经典算法】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、大数据、数据结构算法公众号同名),回复暗号,更能获取学习秘籍和书籍等
相关文章
|
8天前
|
人工智能 安全 Java
Java和Python在企业中的应用情况
Java和Python在企业中的应用情况
35 7
|
2月前
|
数据采集 缓存 Java
Python vs Java:爬虫任务中的效率比较
Python vs Java:爬虫任务中的效率比较
|
5天前
|
算法 数据安全/隐私保护 开发者
马特赛特旋转算法:Python的随机模块背后的力量
马特赛特旋转算法是Python `random`模块的核心,由松本真和西村拓士于1997年提出。它基于线性反馈移位寄存器,具有超长周期和高维均匀性,适用于模拟、密码学等领域。Python中通过设置种子值初始化状态数组,经状态更新和输出提取生成随机数,代码简单高效。
|
16天前
|
机器学习/深度学习 人工智能 算法
基于Python深度学习的【垃圾识别系统】实现~TensorFlow+人工智能+算法网络
垃圾识别分类系统。本系统采用Python作为主要编程语言,通过收集了5种常见的垃圾数据集('塑料', '玻璃', '纸张', '纸板', '金属'),然后基于TensorFlow搭建卷积神经网络算法模型,通过对图像数据集进行多轮迭代训练,最后得到一个识别精度较高的模型文件。然后使用Django搭建Web网页端可视化操作界面,实现用户在网页端上传一张垃圾图片识别其名称。
61 0
基于Python深度学习的【垃圾识别系统】实现~TensorFlow+人工智能+算法网络
|
16天前
|
机器学习/深度学习 人工智能 算法
【手写数字识别】Python+深度学习+机器学习+人工智能+TensorFlow+算法模型
手写数字识别系统,使用Python作为主要开发语言,基于深度学习TensorFlow框架,搭建卷积神经网络算法。并通过对数据集进行训练,最后得到一个识别精度较高的模型。并基于Flask框架,开发网页端操作平台,实现用户上传一张图片识别其名称。
51 0
【手写数字识别】Python+深度学习+机器学习+人工智能+TensorFlow+算法模型
|
16天前
|
机器学习/深度学习 人工智能 算法
基于深度学习的【蔬菜识别】系统实现~Python+人工智能+TensorFlow+算法模型
蔬菜识别系统,本系统使用Python作为主要编程语言,通过收集了8种常见的蔬菜图像数据集('土豆', '大白菜', '大葱', '莲藕', '菠菜', '西红柿', '韭菜', '黄瓜'),然后基于TensorFlow搭建卷积神经网络算法模型,通过多轮迭代训练最后得到一个识别精度较高的模型文件。在使用Django开发web网页端操作界面,实现用户上传一张蔬菜图片识别其名称。
59 0
基于深度学习的【蔬菜识别】系统实现~Python+人工智能+TensorFlow+算法模型
|
20天前
|
算法 Python
在Python编程中,分治法、贪心算法和动态规划是三种重要的算法。分治法通过将大问题分解为小问题,递归解决后合并结果
在Python编程中,分治法、贪心算法和动态规划是三种重要的算法。分治法通过将大问题分解为小问题,递归解决后合并结果;贪心算法在每一步选择局部最优解,追求全局最优;动态规划通过保存子问题的解,避免重复计算,确保全局最优。这三种算法各具特色,适用于不同类型的问题,合理选择能显著提升编程效率。
36 2
|
1月前
|
机器学习/深度学习 人工智能 算法
【车辆车型识别】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+算法模型
车辆车型识别,使用Python作为主要编程语言,通过收集多种车辆车型图像数据集,然后基于TensorFlow搭建卷积网络算法模型,并对数据集进行训练,最后得到一个识别精度较高的模型文件。再基于Django搭建web网页端操作界面,实现用户上传一张车辆图片识别其类型。
74 0
【车辆车型识别】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+算法模型
|
2月前
|
Java 测试技术 程序员
💡Java 零基础 | 深入理解注释的重要性与应用
【10月更文挑战第10天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
28 5
|
2月前
|
机器学习/深度学习 算法 Java
机器学习、基础算法、python常见面试题必知必答系列大全:(面试问题持续更新)
机器学习、基础算法、python常见面试题必知必答系列大全:(面试问题持续更新)