
🎯 题目描述:
给定一个数组
nums,编写一个函数将所有的0移动到数组的末尾,同时保持非零元素的相对顺序不变。你必须在不复制数组的情况下,原地对数组进行操作。
✅ 方法一:快慢指针(推荐,效率高)
💡 核心思路:
-
用两个指针
slow和fast:fast负责找非零元素;slow负责放置非零元素。
-
找到非零元素后就放到
slow指针位置上,slow前进; -
所有非零元素搬完后,
slow后的全填 0 即可。
✅ 时间复杂度:O(n)
✅ 空间复杂度:O(1)
🧠 示例:
输入:[0, 1, 0, 3, 12]
输出:[1, 3, 12, 0, 0]
✅ 代码实现 + 注释
class Solution {
public:void moveZeroes(vector<int>& nums) {int slow = 0; // 慢指针:下一个非零元素应放的位置// 第一步:将非零元素按顺序放到前面for (int fast = 0; fast < nums.size(); fast++) {if (nums[fast] != 0) {nums[slow++] = nums[fast];}}// 第二步:剩下的全填 0while (slow < nums.size()) {nums[slow++] = 0;}}
};
✅ 方法二:使用 erase + push_back(代码直观,但不高效)
💡 思路:
-
遍历数组,用迭代器找 0;
-
每找到一个 0,就:
- 用
erase()删除它(从当前位置删掉); - 然后在末尾
push_back(0)补回来。
- 用
⚠️ 缺点:
- 每次
erase()操作都会导致数组元素移动,时间复杂度 O(n²); - 不适用于大数据量,仅作思路展示。
✅ 代码实现 + 注释
class Solution {
public:void moveZeroes(vector<int>& nums) {for (auto it = nums.begin(); it != nums.end(); ) {if (*it == 0) {it = nums.erase(it); // 删除当前的 0,返回新位置nums.push_back(0); // 在末尾补一个 0} else {++it; // 当前不是 0,继续下一个}}}
};
✅ 总结对比
| 方法 | 时间复杂度 | 空间复杂度 | 是否推荐 | 说明 |
|---|---|---|---|---|
| 快慢指针法 | O(n) | O(1) | ✅ 推荐 | 简洁高效,原地操作 |
erase法 | O(n²) | O(1) | ❌ 不推荐 | 写法直观但效率差 |
