代码链接:https://github.com/xinhui1111/leetcode/blob/master/src/doublePoint.cpp
void moveZeroes(vector<int> &nums)
与 void moveZeroes_Official(vector<int>& (nums))
想看最优的解法(这里的最优只是我已经会实现的最优)可以直接跳转到二、官方解法
零、题目说明
两个要求:
- 将零放在后面;
- 非零的相对位置不能变;
一、自己的解法
最开始错误的解法——遇0首尾互换,相对位置被打乱
原理
首先我是想着直接将双指针一个放在第一个位置上,一个放在最后一个位置,然后两者进行转换,遍历完整个数组。
实现代码
void moveZeroes(vector<int> &nums) {
//这种方法把相对位置变了
//可以从前往后进行推,遇到0就将其放在最后,并且放了之后指向最后的位置就向前移动一位
int left{0};
int right{static_cast<int>(nums.size()-1)};
//前后两个指针,前面一个一步步向后移动,当遇到0就与最后的进行转换,转换了之后后面的指针也要向前移动一个,非0就向后进行移动,
while(left<right){
if(nums[left]==0){
//将这个位置和最后一个位置的数进行互换
if(nums[right]!=0){
//进行互换
int temp{0};
temp=nums[left];
nums[left]=nums[right];
nums[right]=temp;
}
right--;
}
left++;
}
}
优劣
放入官方代码中,检查是否正确:
可以看到是因为顺序不对,这是因为首尾互换打乱了顺序。我们拿出前面的原理图就可以看出来,因为前面没有特别留意到这里顺序被打乱了:
比如这的12就因为在最后,与第一个就换了位置,换到了第一的位置,那么就和之前的相对位置不一样了。
正确的解法——每次遇到0向前平移,效率不高
原理
为了保证相对位置不变,首先想到的最简单的办法就是遇到0的时候就把0放在最后,然后0后面的元素都向前移动一位,同时两个指针位置也要改变。
代码
void moveZeroes(vector<int> &nums) {
int left{0};
int right{static_cast<int>(nums.size()-1)};
while (left<right){
if(nums[left]==0){
//就把left后面的全部往前移动
for(int i=left;i<right;i++){
nums[i]=nums[i+1];
}
nums[right]=0;
right--;
}
else
left++;
}
}
优劣
将其提交,可以看到代码效率很低:
二、官方的解法
原理
将非零值一步步提到最前面,所以关键是移动右指针,遇到非零就把它换到前面,并且是以类似尾插针的方式:
代码实现
/*
* 借鉴了官方的解法
* 将指针放在相邻的位置,如果遇到是0的时候,就把0放在前面
*/
void moveZeroes_Official(vector<int>& (nums)){
int left{0};
int right{0};
while (right<nums.size()){
if(nums[right]){
//将left与right进行互换
int temp{0};
temp=nums[left];
nums[left]=nums[right];
nums[right]=temp;
left++;
}
right++;
}
}
优劣
将其提交,看到效率不错: