题目描述:
给定一个数组 nums
,编写一个函数将所有 0
移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
示例 1:
输入: nums =[0,1,0,3,12]
输出:[1,3,12,0,0]
示例 2:
输入: nums =[0]
输出:[0]
我的解法(暴力):
void moveZeroes(int* nums, int numsSize) {
int j,temp;
for(int i=0;i<numsSize-1;i++){
if(nums[i]==0){
j=i+1;
while(nums[j]==0&&j<numsSize-1) j++;
temp=nums[i];
nums[i]=nums[j];
nums[j]=temp;
}
}
}
分析:用 i 做工作指针遍历数据,当当前遍历元素为0时需要调整元素,用 j 寻找 i 之后的第一个非0元素,将其与 i 交换。整个过程类似于冒泡排序,但由于用了两层循环时间复杂度为n平方。需要注意两处边界判定:由于 j 是从i+1处开始, i 最多只能到 n-1 个元素,由于while使 j+1,必须限制当前 j < n-1,+1后才能不超出边界。
优秀解法(快慢指针):
void moveZeroes(int* nums, int numsSize) {
int slow=0;
for(int i=0;i<numsSize;i++){
int temp=nums[i];
nums[i]=0;
if(temp){
nums[slow++]=temp;
}
}
}
题解来自用户:hLMLV5RJws
分析:这个版本比官方的快慢指针解法更好理解。题目不让复制数组,考虑到遍历元素之前的数据空间已经无用,可以用覆盖的方式更新数组,使得 i 之前的数组为所求新数组, i 之后的数组为题给旧数组。只有当 i 个元素不为0时才需要将其存储到新数组里,此时新数组长度+1,对应slow指针右移。