今天这道题较为简答,因此采用两种解法来写。
这道题较为简单,大家划过即可。
一、题目
给定一个数组 nums
,编写一个函数将所有 0
移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
示例 1:
输入: nums =[0,1,0,3,12]
输出:[1,3,12,0,0]
示例 2:
输入: nums =[0]
输出:[0]
二、代码(队列解法)
class Solution {
public:
void moveZeroes(vector<int>& nums) {
queue<int> que;
for(int n : nums){
if(n!= 0){
que.push(n);//将非零元素加入队列
}
}
size_t i= 0;
while(!que.empty()){//在队列非空时,读取队头元素,并将其依次写入动态数组nums,并将该队头元素出队
nums[i++] = que.front();
que.pop();
}
while( i<nums.size()){//加入零
nums[i++] = 0 ;
}
// for(size_t i = 0 ; i < nums.size() ; i++ ){//刚开始采用for循环,发生超时,改用while循环后解决问题
// nums[i] = que.front();
// que.pop();
// while(que.empty()){
// nums[i] = 0 ;
// }
// }
}
};
对于队列解法的理解
首先创建队列,然后遍历nums,将非零元素加入队列,后通过while循环依次让队列元素出队,并加入数组,最后,用while循环将0元素填充至数组nums。这里注意nums.size()返回的是size_t型变量。
三、代码(双指针解法)
class Solution {
public:
void moveZeroes(vector<int>& nums) {
size_t aft;
size_t fro;
for(aft = -1,fro = 0; fro<nums.size() ; fro++){
if(nums[fro]){
swap(nums[++aft],nums[fro]);
}
}
}
};
对于双指针解法的理解
首先初始化俩个指针,前fro后aft,初始时,fro指向0,aft指向-1。
以 [0,1,0,3,12] 为例子,解释这个过程,此时nums[fro]=0,不满足条件,因此fro++,对应元素为1,满足条件,aft自增,交换两元素的值,序列变为 [1,0,0,3,12] fro自增,此时aft指向元素下标为0,fro->数组下标2,不满足条件,fro++,fro->数组下标3,满足条件,aft自增后交换两值,发现fro总是在寻找非零数,而aft在0元素的前面,每次aft自增后,交换两值,从而实现非零元素在前,零元素在后。