566 字
1 分钟
移动零
题目描述
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
请注意,必须在不复制数组的情况下原地对数组进行操作。
输入
整数数组 nums
输出
无返回值,原地修改 nums
约束条件
1 <= nums.length <= 10^4-2^31 <= nums[i] <= 2^31 - 1
进阶约束
- 能否尽量减少操作次数?
示例1
input: nums = [0,1,0,3,12]output: [1,3,12,0,0]示例2
input: nums = [0]output: [0]解题思路
题目要求把数组中的 0 全部挪到末尾,同时非零元素之间的相对顺序不能变,并且必须原地修改,不能另开数组。
从直观做法出发
最容易想到的是:先统计 0 的个数,再把非零元素按顺序填到前面,最后把剩余位置全部填 0。思路没问题,但通常需要额外数组或两次遍历,不够简洁。
另一种想法是:从左到右扫描,每遇到一个非零元素,就把它「写」到当前应该存放的位置。非零元素按扫描顺序依次写入,空出来的位置自然就是 0 了——这正是双指针能做的事。
双指针:一个扫描,一个写入
用两个指针 i 和 j,初始都为 0:
i:从左到右扫描整个数组j:指向下一个非零元素应该写入的位置
遍历过程中,若 nums[i] 非零,就把它交换到 nums[j],然后 j 加一;若 nums[i] 为零,则什么都不做,继续让 i 往后走。
以 nums = [0, 1, 0, 3, 12] 为例:
i | nums[i] | 操作 | nums | j |
|---|---|---|---|---|
| 0 | 0 | 跳过 | [0,1,0,3,12] | 0 |
| 1 | 1 | 交换 nums[1] 与 nums[0] | [1,0,0,3,12] | 1 |
| 2 | 0 | 跳过 | [1,0,0,3,12] | 1 |
| 3 | 3 | 交换 nums[3] 与 nums[1] | [1,3,0,0,12] | 2 |
| 4 | 12 | 交换 nums[4] 与 nums[2] | [1,3,12,0,0] | 3 |
遍历结束后,j 之后的元素本来就是 0 或被交换过来的 0,上表最后一行即为最终结果。
当 i == j 时交换等于没交换,因此非零元素在「前面没有零」的情况下不会被多余地移动,相对顺序也始终得以保持。
复杂度
- 时间复杂度:,只遍历数组一次
- 空间复杂度:,仅使用常数额外空间
代码
class Solution: def moveZeroes(self, nums: List[int]) -> None: """ Do not return anything, modify nums in-place instead. """ i = j = 0 for i in range(len(nums)): if nums[i]: nums[i], nums[j] = nums[j], nums[i] j += 1 分享
如果这篇文章对你有帮助,欢迎分享给更多人!
部分信息可能已经过时
相关文章 智能推荐









