[leetcode] Move Zeroes

Given an array nums, write a function to move all 0's to the end of it while maintaining the relative order of the non-zero elements.

Example:

Input: [0,1,0,3,12]
Output: [1,3,12,0,0]

Note:

  1. You must do this in-place without making a copy of the array.
  2. Minimize the total number of operations.

分析:题目翻译一下:要求将数组中0元素移动到最后,并且保持非0元素的顺序。
最基础的想法就是类似冒泡,发现一个0就不停的往后移,时间复杂度是O(n^2)。不好,直接舍弃。
第二个想法,如果发现一个0,就与之后的第一个非0元素交换位置。这样又把0往后移动,又保持了非0元素的位置。其实思想就是Two Pointers。代码如下:
class Solution {
    public void moveZeroes(int[] nums) {
        for ( int left = 0 ; left < nums.length - 1 ; left++ ) {
            if (nums[left] == 0) {
                int right = left + 1;
                while (right < nums.length) {
                    if (nums[right] != 0) {
                        swap(nums, left, right);
                        break;
                    }
                    right++;
                }
            }
        }
    }

    private void swap(int[] nums, int left, int right) {
        int temp = nums[left];
        nums[left] = nums[right];
        nums[right] = temp;
    }
}

    运行时间17ms,击败9.00%的提交。显然还是有很大的提升空间的。

第三个思路:我认为上面用Two Pointers的思路是正确的,为什么这么多时间浪费了呢,分析一下原因:right指针做了很多重复性的工作。例如[1,0,0,3,12]中,left指向第一个0,和left指向第2个0,right指针动作都是相同(类似)的,如果连续有很多个0,那么right指针就会非常浪费时间。因此用Two Pointer的思路来了:right指针总是指向第一个非0的元素,left指针总是指向第一个0元素。然后交换两个位置。代码如下:

 1 class Solution {
 2     public void moveZeroes(int[] nums) {
 3         int left = 0;
 4         int right = 0;
 5         while ( right < nums.length ){
 6             while ( nums[right] == 0 && right < nums.length - 1 ) right++;
 7             if ( nums[left] == 0 ) swap(nums,left,right);
 8             left++;
 9             right++;
10         }
11     }
12     private void swap(int[] nums, int left, int right) {
13         int temp = nums[left];
14         nums[left] = nums[right];
15         nums[right] = temp;
16     }
17 }

      运行时间1ms,击败100%的提交。这里一定要注意第6行的边界条件。卡在这错了好几个。。。right的值在变化的过程中一定要满足6行的条件。

      第二种方法才是Two Pointers的精髓啊!!!两个指针一定要是独立的,第一个方法虽然也是两个指针但是时间复杂度是O(nlogn),而且right指针是依附于left的。日渐感受到双指针的优势。

原文地址:https://www.cnblogs.com/boris1221/p/9356161.html