* [做项目（多个C++、Java、Go、测开、前端项目）](https://www.programmercarl.com/other/kstar.html)
* [刷算法（两个月高强度学算法）](https://www.programmercarl.com/xunlian/xunlianying.html)
* [背八股（40天挑战高频面试题）](https://www.programmercarl.com/xunlian/bagu.html)

# 283. 移动零：动态规划：一样的套路，再求一次完全平方数

[力扣题目链接](https://leetcode.cn/problems/move-zeroes/)

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

示例:

输入: [0,1,0,3,12]
输出: [1,3,12,0,0]
说明:

必须在原数组上操作，不能拷贝额外的数组。
尽量减少操作次数。


## 思路

做这道题目之前，大家可以做一做[27.移除元素](https://programmercarl.com/0027.移除元素.html)

这道题目，使用暴力的解法，可以两层for循环，模拟数组删除元素（也就是向前覆盖）的过程。

好了，我们说一说双指针法，大家如果对双指针还不熟悉，可以看我的这篇总结[双指针法：总结篇！](https://programmercarl.com/双指针总结.html)。

双指针法在数组移除元素中，可以达到O(n)的时间复杂度，在[27.移除元素](https://programmercarl.com/0027.移除元素.html)里已经详细讲解了，那么本题和移除元素其实是一个套路。

**相当于对整个数组移除元素0，然后slowIndex之后都是移除元素0的冗余元素，把这些元素都赋值为0就可以了**。

如动画所示：

![移动零](https://file1.kamacoder.com/i/algo/283.%E7%A7%BB%E5%8A%A8%E9%9B%B6.gif)

C++代码如下：

```CPP
class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int slowIndex = 0;
        for (int fastIndex = 0; fastIndex < nums.size(); fastIndex++) {
            if (nums[fastIndex] != 0) {
                nums[slowIndex++] = nums[fastIndex];
            }
        }
        // 将slowIndex之后的冗余元素赋值为0
        for (int i = slowIndex; i < nums.size(); i++) {
            nums[i] = 0;
        }
    }
};
```

## 其他语言版本

### Java：

```java
public void moveZeroes(int[] nums) {
        int slow = 0;
        for (int fast = 0; fast < nums.length; fast++) {
            if (nums[fast] != 0) {
                nums[slow++] = nums[fast];
            }
        }
        // 后面的元素全变成 0
        for (int j = slow; j < nums.length; j++) {
            nums[j] = 0;
        }
    }
```

### Python：

```python
    def moveZeroes(self, nums: List[int]) -> None:
        slow = 0
        for fast in range(len(nums)):
            if nums[fast] != 0:
                nums[slow] = nums[fast]
                slow += 1
        for i in range(slow, len(nums)):
            nums[i] = 0
```
交换前后变量，避免补零
```python
    def moveZeroes(self, nums: List[int]) -> None:
        slow, fast = 0, 0
        while fast < len(nums):
            if nums[fast] != 0:
                nums[slow], nums[fast] = nums[fast], nums[slow]
                slow += 1 # 保持[0, slow)区间是没有0的
            fast += 1
```

### Go：

```go
func moveZeroes(nums []int)  {
    slow := 0
    for fast := 0; fast < len(nums); fast ++ {
        if nums[fast] != 0 {
            temp := nums[slow]
            nums[slow] = nums[fast]
            nums[fast] = temp
            slow++
        }
    }
}
```

### JavaScript：

```javascript
var moveZeroes = function(nums) {
    let slow = 0;
    for(let fast = 0; fast < nums.length; fast++){
        if(nums[fast] != 0){//找到非0的元素
            nums[slow] = nums[fast];//把非0的元素赋值给数组慢指针指向的索引处的值
            slow++;//慢指针向右移动
        }
    }
    // 后面的元素全变成 0
    for(let j = slow; j < nums.length; j++){
        nums[j] = 0;
    }
};
```

### TypeScript：

```typescript
function moveZeroes(nums: number[]): void {
    const length: number = nums.length;
    let slowIndex: number = 0,
        fastIndex: number = 0;
    while (fastIndex < length) {
        if (nums[fastIndex] !== 0) {
            nums[slowIndex++] = nums[fastIndex];
        };
        fastIndex++;
    }
    while (slowIndex < length) {
        nums[slowIndex++] = 0;
    }
};
```

### C

```c
void moveZeroes(int* nums, int numsSize){
    int fastIndex = 0, slowIndex = 0;
    for (; fastIndex < numsSize; fastIndex++) {
        if (nums[fastIndex] != 0) {
            nums[slowIndex++] = nums[fastIndex];
        }
    }

    // 将slowIndex之后的元素变为0
    for (; slowIndex < numsSize; slowIndex++) {
        nums[slowIndex] = 0;
    }
}
```

### Rust
```rust
impl Solution {
    pub fn move_zeroes(nums: &mut Vec<i32>) {
        let mut slow = 0;
        for fast in 0..nums.len() {
            if nums[fast] != 0 {
                nums.swap(slow, fast);
                slow += 1;
            }
        }
    }
}
```



