LEETCODE(力扣)283. 移动零
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
示例 1:
输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]
示例 2:
输入: nums = [0]
输出: [0]
提示:
1 <= nums.length <= 104
-231 <= nums[i] <= 231 - 1
进阶:你能尽量减少完成的操作次数吗?
自解
1.双指针for遍历

时间、空间,都只能用悲惨来形容。
//从后往前遍历0?
//好像与从前往后没什么区别?不,少遍历了0,更优
//两个指针,一个记录0最靠前的位置,一个进行遍历
void moveZeroes(int* nums, int numsSize) {
int *p1=nums+numsSize;
int *pzero=p1;
int temp=0;
for(int i=numsSize-2;i>0;i--)
{
if(nums[i]==0)
{
p1=nums+i;
while(p1!=pzero-1)
{
temp=*p1;
*p1=*(p1+1);
*(p1+1)=temp;
p1++;
}
pzero--;
}
}
if(nums[0]==0)
{
p1=nums;
while(p1!=pzero-1)
{
temp=*p1;
*p1=*(p1+1);
*(p1+1)=temp;
p1++;
}
pzero--;
}
}
2.双指针分段

看了官方解答例子后自写,效果非常好
void swap(int *a,int *b)//交换函数
{
int temp=0;
temp=*a;
*a=*b;
*b=temp;
}
/*可理解数组分为三段:
处理段 零段 未处理段
左指针:指向处理段后面一个位置,也就是零段第一个零
右指针:记录未处理段的第一个位置,同时对数组进行遍历
当右指针遇到非零数,交换左右两指针值,也就相当将该非零数移动到了处理段
*/
void moveZeroes(int* nums, int numsSize) {
int *left,*right;
left=nums;
right=left;
while(right<nums+numsSize)//要处理完数组最后一个数才推出循环
{
if(*right==0)//右指针指向的数为0
{
while(*right==0&&right<nums+numsSize-1)right++;/*遍历到不为零,或者右指针指向数组最后一个数
-1是为了让右指针不溢到数组外*/
swap(left,right);//交换,将非零数换到
}
else//右指针指向的数非0,直接交换
{
swap(left,right);
}
right++;
left++;
}
}
官方解答
分段的思路,而且更简洁
void swap(int *a, int *b) {
int t = *a;
*a = *b, *b = t;
}
void moveZeroes(int *nums, int numsSize) {
int left = 0, right = 0;
while (right < numsSize) {
if (nums[right]) {
swap(nums + left, nums + right);
left++;
}
right++;
}
}
作者:力扣官方题解
链接:https://leetcode.cn/problems/move-zeroes/solutions/489622/yi-dong-ling-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

浙公网安备 33010602011771号