zoukankan      html  css  js  c++  java
  • [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的。日渐感受到双指针的优势。

  • 相关阅读:
    [BZOJ4318] WJMZBMR打osu! / Easy (期望DP)
    构建之法阅读笔记05
    个人冲刺04
    构建之法阅读笔记04
    个人冲刺03
    个人冲刺02
    冲刺——第一天
    第八周学习进度条
    构建之法阅读笔记03
    第七周学习进度条
  • 原文地址:https://www.cnblogs.com/boris1221/p/9356161.html
Copyright © 2011-2022 走看看