文章

Leetcode--283. 移动零

Leetcode--283. 移动零

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

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

示例1

// 快慢指针+小优化
class Solution {
    public void moveZeroes(int[] nums) {
        int slow = 0;
        for(int fast = 0; fast < nums.length; fast++) {
            if(nums[fast] != 0) {
                // 这里主要是将指向i和j的元素进行交换
                if(nums[slow] != nums[fast]) {
                    int temp = nums[slow];
                    nums[slow] = nums[fast];
                    nums[fast] = temp;
                }
                slow++; // 注意一定不能忘记这里需要++
            }
        }
        return;
    }
}

这里参考了快速排序的思想,快速排序首先要确定一个待分割的元素做中间点 x,然后把所有小于等于 x 的元素放到 x 的左边,大于 x 的元素放到其右边。

这里我们可以用 0 当做这个中间点,把不等于 0(注意题目没说不能有负数)的放到中间点的左边,等于 0 的放到其右边。 这的中间点就是 0 本身,所以实现起来比快速排序简单很多,我们使用两个指针 fast 和 slow,只要 nums[i]!=0,我们就交换 nums[i] 和 nums[j]

i和j的相对位置是:【已经处理好的数据】slow【全是需要被交换的0】fast【未处理的数据】。 然后i始终去找非0的数据进行交换,每次交换完,j的位置变成处理好的非0数据向后移动一个位置,等待i找到下一个需要交换的非0数据

我的笨办法:

参考冒泡排序,将0与后面对换,但是缺点是双重循环且循环次数最多为nums.length的阶乘,效率低下

class Solution {
    public void moveZeroes(int[] nums) {
        int tmp = 0;
        int count = nums.length - 1;
        for (int j = 0; j < count; j++) {
            for (int i = 0; i < count - j; i++) {
                tmp = nums[i + 1];
                if (nums[i] == 0) {
                    nums[i + 1] = nums[i];
                    nums[i] = tmp;
                }
            }
        }
    }
}
License:  CC BY 4.0