leetcode_283.移动零
题目如下
本道题采用双指针的思想完成,可以使用快慢指针的思想,通过快指针遍历数组找出数组中的非零元素,用慢指针来维护有效值
可以先根据题目的条件手搓出来一个测试,方便理解
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
void moveZeroes(vector<int>& nums) {//方法一:快慢指针int fast=0,slow=0;for(fast=0;fast<nums.size();fast++){if(nums[fast]!=0){nums[slow++]=nums[fast];}}cout<<"fast "<<fast<<'\n';cout<<"slow "<<slow<<'\n';}
int main()
{vector<int>v(5);for(int i=0;i<5;i++){int x;cin>>x;v[i]=x;}moveZeroes(v);for(int i=0;i<5;i++){cout<<v[i]<<" ";}return 0;
}
例如题目的案例一:0 1 0 3 12
先自己模拟一遍,刚开始 fast
和slow
指针都指向 0
号索引,开始向后找,一旦发现不为 0
的元素,就将其填在slow
索引处,第一次发生在索引为1
的时候,经过操作,得到了1 1 0 3 12
此时slow
进行自增指向索引1
,第二次发生在索引为3
的时候,经过操作得到了1 3 0 3 12
,第三次发生在索引为4
的时候,经过操作得到了1 3 12 3 12
,最终遍历完毕,fast最后指向了索引5
,slow最后指向了索引3
验证一下:
没错是这样的,这样就找到了数组中所有不为0
的数字,且由slow
来维护。最后我们只需要将slow-fast
之间的数字全部变为0
就可以了
//就相当于slow到数组的最后for(int i=slow;i<nums.size();i++){nums[i]=0;}//两种都可以for(int i=slow;i<fast;i++){nums[i]=0;}
AC代码:
class Solution {
public:void moveZeroes(vector<int>& nums) {//方法一:快慢指针int fast=0,slow=0;for(fast=0;fast<nums.size();fast++){if(nums[fast]!=0){nums[slow++]=nums[fast];}}for(int i=slow;i<fast;i++){nums[i]=0;}}
};
还有另外一种方法:
定义 l 和 r 指针,通过 r 指针遍历数组,找到不为 0 的元素,依次交换
还是以0 1 0 3 12
为例子:
刚开始 l 和 r
都指向0
号索引,r
向前遍历,当找到不为0
的数字时和索引为 l
的数字进行交换,第一次找到了1
跟l(0)
交换得到了1 0 0 3 12
此时l 自增->(1)
,第二次找到了3
进行交换,得到了1 3 0 0 12
,l自增->(2)
,第三次找到了12
,进行交换得到了1 3 12 0 0
即是最终答案,此时l = 3 r= 5
最终也可以得到正确答案:
AC代码:
class Solution {
public:void moveZeroes(vector<int>& nums) {int l=0,r=0;while(r<nums.size()){if(nums[r]!=0){swap(nums[l],nums[r]);l++;}r++;}}
};