题目:移动零
废话(可跳过)
回顾下学习JVM时垃圾回收的标记整理法
,首先将存活的对象
进行标记,然后把标记好的对象向一端进行移动,然后将端界限之外的非标记对象
全部清理掉。
再看这道题,是不是很像,把非0
的数字往前移动,最终将0
和非0
的数组化为两段。题目源于工程开发,平时多刷刷题目,对日后的工作开发大有裨益啊。
分析
这道题如果不要求空间复杂度O(1)
将会很简单,创建一个等长的新数组,遍历一遍,遇到非0
的元素就放在新数组里。而要求O(1)
也就说,只能在原数组内活动,那么我们只需要一个指针,来记录遇到的非0
元素的个数即可。
思路
- 特判: 过滤掉空数组;
- 定义一个指针
p
表示已经遇到的非0
元素的个数,初始值为0
; - 遍历:
- 遇到
非0
的元素就放在p
的位置上,然后p++
;
- 遇到
代码
class Solution {
public void moveZeroes(int[] nums) {
if(nums == null || nums.length == 0){
return;
}
int p = 0;
int len = nums.length;
for(int i = 0; i < len; i++){
if(nums[i] != 0){
int tmp = nums[i];
nums[i] = nums[p];
nums[p++] = tmp;
}
}
}
}
如果上述代码看懂了,跳过~
只有遍历到的nums[i]
全为非0
时,p
和i
保持相同大小,如果遇到0
元素,那么i
直接跳过继续i++
,而p
则会停留在为0
元素的位置上,这也是为什么要nums[i]
和nums[p]
互换,只有这样才能在一次遍历中把非0元素位置的元素变为0
。
看懂点赞,看不懂留言~