学完了数据结构和C++的STL库,我们需要开始学习算法了。有了前面的基础知识储备,再好好学习算法,有系统,有规律的刷题,总结,咱们的编程能力就会有质的飞跃!
1.题目
我们用一个例题来讲解这个算法。
题目的要求我们把0都移动到数组的最后面,且不改变非0元素的顺序。
这个题目可以归为数组划分,数组分块里面。这类题目我们首先应该想到双指针算法!
2.算法讲解
双指针的作用:
1.cur:负责遍历数组,查找非0元素。
2.dest:在cur扫描过的区间内,起到划分非0元素和0元素的作用。
有了这两个指针,数组就被我们划分为三个区间:
【0,dest】这个区间全是非0元素。(换句话说:dest指向非0元素的最后一个值)。
【dest+1,cur-1】这个区间全是0元素。
【cur,n-1】这个区间是未扫描区间。
如果在cur扫描数组的过程中,这三个区间中的元素始终能保持对应的性质,就可以满足题意。
2.1具体步骤
如何能做到呢:
提到指针,可能会勾起大家当初学C语言指针部分那段痛苦的回忆,其实数组下标的底层就是指针的解引用,我们可以用数组下标代替指针!
首先初始化:cur=0,dest=-1。(不要问为什么,看完具体实现后自然就明白了!)。
在cur遍历数组的过程中,需要做的操作:
1.遇到0:cur++。
2.遇到非零:swap(nums[dest+1],nums[cur]) ,dest++,cur++。(假设数组名是nums)。
3.代码实现与提交结果
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int cur=0,dest=-1,size=nums.size();
while(size--){
if(nums[cur]==0)
cur++;
else{
swap(nums[dest+1],nums[cur]);
dest++;
cur++;
}
}
}
};
分析代码我们可以看到:
1.该算法只遍历了一次数组,所以时间复杂度是O(n)。
2.创建了dest,cur,size三个变量,所以空间复杂度是O(1)。
如果你的代码能力很好,那么下面这种写法也是可以的!