力扣hot100-283移动零(盲人拉屎)

283. 移动零 - 力扣(LeetCode)

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

示例 1:

复制代码
输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]

示例 2:

复制代码
输入: nums = [0]
输出: [0]

提示:

  • 1 <= nums.length <= 104

  • -231 <= nums[i] <= 231 - 1

**进阶:**你能尽量减少完成的操作次数吗?

相当于把在不改变所有非零元素的相对顺序的前提下将其移动到数组的最前端。最直观的思路就是遍历数组,遇到非零元素就往前扔。那么新问题来了:扔到哪里?所以就需要再声明一个变量去标记应该扔到哪里。这很像双指针,所以不妨右指针一直往后找非零元素,找到了,就把非零元素扔到左指针所在的位置。一旦左指针所在的位置为非零元素,左指针就要往后移动一位,否则就是占着茅坑不拉屎:因为左指针的用处本来就是标记下一个非零元素应该放到哪里,现在它的位置已经被占了,就应该往后挪。

粗俗地说,右指针是一位盲人,非零元素好比右指针拉的屎,左指针是它的导盲犬,它告诉右指针应该往哪里拉屎。如果一个坑已经被屎填满了,那导盲犬应该移动到下一个空的坑位,这样右指针才能知道它下一次应该把屎拉在哪里。

需要注意的是,覆盖和交换略有差别。如果是覆盖,那么最终就要再从左指针left的位置开始,往后面遍历直到数组末尾,将这中间遇到的所有元素都赋值为0.因为没有交换。之所以是从left开始,不是left+1或left-1,是因为left本来就是标记下一个非零元素应该扔到哪里,而最后非零元素一定都被扔到left前面了,所以left开始后面的茅坑必须不能被屎填满。如果遇到了全部为0的数组,那么对于覆盖就要遍历两次数组。但交换的话就不需要考虑这个。

Java:

java 复制代码
class Solution {
    public void moveZeroes(int[] nums) {
        //右指针一直往后移,遇到非零元素,就往前扔
        //具体扔到哪里,由左指针控制。扔到左指针所在的位置
        int left=0,right=0,n=nums.length;
        while(right<n) {
            if(nums[right] != 0) {
                //交换
                int temp = nums[left];
                nums[left] = nums[right];
                nums[right] = temp;
                left++;
            }
            right++;
        }
        //如果是覆盖,那么对于一个全部为0的数组,要遍历两次
    }
}

Go:

Go 复制代码
func moveZeroes(nums []int)  {
    left,right,n := 0,0,len(nums)
    for right < n {
        if nums[right] != 0 {
            temp := nums[left] 
            nums[left] = nums[right]
            nums[right] = temp
            left++
        }
        right++
    }
}

C++:

cpp 复制代码
class Solution
{
public:
    void moveZeroes(vector<int>& nums)
    {
        int n = nums.size();
        int left = 0, right = 0;
        while (right < n)
        {
            if (nums[right])
            {
                swap(nums[left], nums[right]);
                left++;
            }
            right++;
        }
    }
};
相关推荐
POLITE31 小时前
Leetcode 94. 二叉树的中序遍历 104. 二叉树的最大深度 226. 翻转二叉树 101. 对称二叉树 (Day 13)
算法·leetcode·职场和发展
老鼠只爱大米1 小时前
LeetCode经典算法面试题 #2:两数相加(迭代法、字符串修改法等多种实现方案详解)
算法·leetcode·链表·两数相加·字符串修改法·两数相减·大数运算
季明洵2 小时前
二分搜索、移除元素、有序数组的平方、长度最小的子数组
java·数据结构·算法·leetcode
Sheep Shaun2 小时前
深入理解AVL树:从概念到完整C++实现详解
服务器·开发语言·数据结构·c++·后端·算法
_leoatliang2 小时前
基于Python的深度学习以及常用环境测试案例
linux·开发语言·人工智能·python·深度学习·算法·ubuntu
leiming62 小时前
C语言联合体union的用法(非常详细,附带示例)
java·python·算法
YuTaoShao2 小时前
【LeetCode 每日一题】3314. 构造最小位运算数组 I —— (解法二)
算法·leetcode·职场和发展
薛定e的猫咪2 小时前
【NeurIPS 2023】多目标强化学习算法工具库-MORL-Baselines
人工智能·算法·机器学习
Sarvartha2 小时前
单链表的插入和合并以及双链表的删除
算法