思路1
分析
在i位置遇到0,把后面的元素向前移动覆盖,然后把最后一个位置赋值为0即可
注意问题:
可能 i 一个位置 移动一次之后还是0,需要循环
有可能 i 位置的0 是因为 已经所有的0都到后面了
所以需要用count记录0的个数,当所有0都移动完了就break,否则会死循环
代码
void moveZeroes(int* nums, int numsSize){
//在i位置遇到0
//把i+1到最后的元素向前移动
//然后把0放到最后
//找出0的个数
int count=0;
for(int i=0;i<numsSize;i++)
{
if(nums[i]==0)
{
count++;
}
}
for(int i=0;i<numsSize-1;i++)
{
while(nums[i]==0)
{
//这里需要让0的数量--
//如果已经让所有的0全部到最后面了,就不需要移动了
if(count==0)
{
break;
}
//移动
for(int j=i;j<numsSize-1;j++)
{
nums[j]=nums[j+1];
}
//移动之后把最后一个元素置为0
nums[numsSize-1]=0;
count--;
}
}
}
思路2(效率高)
双指针法
end去找非0,放到src位置
最后end走到numsSize,src位置就是最后一个非0的下一个位置
把src后面的置0
最后:
代码
void moveZeroes(int* nums, int numsSize){
//end去找非0,放到src位置
//最后end走到numsSize,src位置就是最后一个非0的下一个位置
//把src后面的置0
int src=0;
int end=0;
while(end<numsSize)
{
if(nums[end]!=0)
{
nums[src]=nums[end];
++src;
}
++end;
}
//把src后面的置0
memset(nums+src,0,sizeof(int)*(numsSize-src));
}
不用memset的方法
当end位置为非0的时候
其实可以直接把src位置和end位置的元素进行交换
如图:
可以发现 src和end交换的过程就是一直把0向后换
如果 数组没有0
那么src和end一直自己交换,也是正确的!
总结:
src和end位置交换
- 要么就是把0向后换
- 要么就是自己与自己交换