- 作者简介:阿里非典型程序员一枚 ,记录在大厂的打怪升级之路。 一起学习Java、大数据、数据结构算法(公众号同名)
- ❤️觉得文章还不错的话欢迎大家点赞👍➕收藏⭐️➕评论,💬支持博主,记得点个大大的
关注
,持续更新🤞
————————————————-
移动零
- 标签(题目类型):数组,双指针
题目描述
给定一个数组 nums
,编写一个函数将所有 0
移动到数组的末尾,同时保持非零元素的相对顺序。
示例:
输入: [0,1,0,3,12]
输出: [1,3,12,0,0]
说明:
必须在原数组上操作,不能拷贝额外的数组。
尽量减少操作次数。
原题:283. 移动零
思路及实现
方式一:双指针
思路
使用两个指针 i
和 j
,i
用于遍历数组,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) |
相似题目
欢迎一键三连(关注+点赞+收藏),技术的路上一起加油!!!代码改变世界
- 关于我:阿里非典型程序员一枚 ,记录在大厂的打怪升级之路。 一起学习Java、大数据、数据结构算法(公众号同名),回复暗号,更能获取学习秘籍和书籍等