283. 移动零 - 力扣(LeetCode) (leetcode-cn.com)
目录
方案1:冒泡(巨慢)
运行结果
代码
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int beg = 0, N = nums.size();
while (beg != N && nums[beg]) ++beg;
if (beg == N) return;
for (int count = 1; count != N; ++count) {
bool no_op = true;
for (int bubble = beg; bubble != N - count; ++bubble) {
if (!nums[bubble] && nums[bubble + 1]) {
swap(nums[bubble], nums[bubble + 1]);
no_op = false;
}
}
if (no_op) return;
}
}
};
方案2:化用快速排序的手段
运行结果
代码
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int i = -1, j = -1, N = nums.size();
while(++j != N) if(nums[j]) swap(nums[++i], nums[j]);
}
};
最佳方案:方案2改进版
不难发现方案2其实是有多余的操作的。我们知道当 j 到达数组尾部、循环结束的时候,从i + 1到 j 位置的元素应该全部为0,我们只需要最终保证其如此,至于中间过程中i + 1~ j 之间是否全部为0无关紧要。因此当 j 定位到一个非0元素之后根本不需要和i + 1位置的元素相交换,只需要把它放到i + 1位置上即可,当 j 到达数组尾部之后,再把i + 1到 j 位置上的元素全部置0也不迟。这样就不需要交换操作,只需要一步赋值操作就行了,提高了代码效率。
代码
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int i = -1, j = -1, N = nums.size();
while(++j != N) if(nums[j]) nums[++i] = nums[j];
while(++i != N) nums[i] = 0;
}
};
运行结果