【LeetCode Hot 100】移动零
1. 移动零
题目链接:LeetCode 移动零
问题描述
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。要求:
- 必须原地操作,不能拷贝数组
- 尽量减少操作次数
示例
示例1
输入:[0,1,0,3,12]
输出:[1,3,12,0,0]
示例2
输入:[0]
输出:[0]
解题思路
双指针法(最优解)
- 快慢指针:使用两个指针
left和right - 指针分工:
right指针遍历数组left指针标记非零元素的插入位置
- 操作过程:
- 当
nums[right] != 0时,交换nums[left]和nums[right] - 保持
left左侧都是非零元素
- 当
将上述思路整理后改写成下面的代码版本:
class Solution {
public:
void moveZeroes(vector<int>& nums) {
//双指针,用一个tag表示 当遍历到i不为0时,[tag , i-1]都是0
//每次把非0的与tag交换,tag再++ , 第i位也会变成0
int tag = 0; //初始时为0
for (int& x : nums)
{
if ( x )
{
swap(nums[tag++] , x);
}
}
}
};
复杂度分析
• 时间复杂度:O(n),只需遍历数组一次
• 空间复杂度:O(1),只使用了常数个额外空间
关键点说明
- 原地操作:直接在原数组上进行修改,不创建新数组
- 保持顺序:非零元素的相对顺序保持不变
- 高效性:只需一次遍历即可完成操作
- 边界处理:自动处理全零数组或单元素数组的情况
扩展思考
- 如果要求将所有零移动到数组开头而非末尾,该如何修改算法?
- 如何统计移动零的总操作次数?
- 这种方法是否适用于其他特定值的移动(如移动所有1)?
提示:在实际编程中,可以尝试用不同的指针命名方式(如slow/fast)来帮助理解算法逻辑
浙公网安备 33010602011771号