移动零
给定一个数组
nums
,编写一个函数将所有0
移动到数组的末尾,同时保持非零元素的相对顺序。请注意 ,必须在不复制数组的情况下原地对数组进行操作。
示例 1:
输入: nums = [0,1,0,3,12] 输出: [1,3,12,0,0]
示例 2:
输入: nums = [0] 输出: [0]
算法思路
这个题我们可以用到快排的思想: 数组划分区间
可以使用一个cur
指针扫描整个数组, 另外用一个dest
指针来记录非零元素序列的最后一个位置. 根据cur
再扫描过程中遇到的不同情况, 进行不同处理. 再cur
遍历期间, 使[0, dest]
的元素全部都是非零元素, [dest + 1, cur - 1]
的元素全是零.
算法流程
- 初始化
cur = 0
(用来遍历数组),dest = -1
(指向非零元素序列的最后一个位置, 因为一开始我们不知道最后一个非零元素在哪, 所以初始化为1) cur
依次往后遍历每个元素, 遍历到的元素会有以下两种情况:- 遇到的元素是
0
,cur
直接++
. 因为我们的目标是让[dest + 1, cur - 1]
的元素全是零, 因此cur
遇到0
时, 直接++
, 就可以让0
再cur - 1
的位置上, 从而在[dest + 1, cur - 1]
内. - 遇到的元素不是
0
,dest++
, 并且交换cur
位置和dest
位置的元素, 之后cur++
, 扫描下一个元素.- 因为
dest
指向的位置时非零元素序列的最后一个位置, 如果扫描到一个新元素也非零, 那么他的位置就应该在dest + 1
的位置上, 因此dest
应先++
dest++
后, 指向的就是0
, 因此可以直接换到cur
位置上, 实现[0, dest]
的元素全部都是非零元素,[dest + 1, cur - 1]
的元素全是零.
- 因为
- 遇到的元素是
Java实现代码
class Solution {public void moveZeroes(int[] nums) {for(int cur = 0, dest = -1; cur < nums.length; cur++) {if(nums[cur] != 0) {dest++;int tmp = nums[cur];nums[cur] = nums[dest];nums[dest] = tmp;}}}
}
时间复杂度: O(N) 空间复杂度O(1)