zoukankan      html  css  js  c++  java
  • [Algorithm] 283. 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.
    var moveZeroes = function(nums) {
        let pos = 0;
        // keep all the non-zero
        for (let i = 0; i < nums.length; i++) {
            if (nums[i] !== 0) {
                nums[pos++] = nums[i];
            }
        }
        
        // add all zero numbers
        for (let i = pos;i < nums.length; i++) {
            nums[pos++] = 0;
        }
    };

    This approach works the same way as above, i.e. , first fulfills one requirement and then another. The catch? It does it in a clever way. The above problem can also be stated in alternate way, " Bring all the non 0 elements to the front of array keeping their relative order same".

    This is a 2 pointer approach. The fast pointer which is denoted by variable "cur" does the job of processing new elements. If the newly found element is not a 0, we record it just after the last found non-0 element. The position of last found non-0 element is denoted by the slow pointer "lastNonZeroFoundAt" variable. As we keep finding new non-0 elements, we just overwrite them at the "lastNonZeroFoundAt + 1" 'th index. This overwrite will not result in any loss of data because we already processed what was there(if it were non-0,it already is now written at it's corresponding index,or if it were 0 it will be handled later in time).

    After the "cur" index reaches the end of array, we now know that all the non-0 elements have been moved to beginning of array in their original order. Now comes the time to fulfil other requirement, "Move all 0's to the end". We now simply need to fill all the indexes after the "lastNonZeroFoundAt" index with 0.

    Complexity Analysis

    Space Complexity : O(1)O(1). Only constant space is used.

    Time Complexity: O(n). However, the total number of operations are still sub-optimal. The total operations (array writes) that code does is nn (Total number of elements).

    var moveZeroes = function(nums) {
        // keep all the non-zero
        for (let i = 0, pos = 0; i < nums.length; i++) {
            if (nums[i] !== 0) {
                [nums[pos], nums[i]] = [nums[i], nums[pos]];
                pos++
            }
        }
    };

    The total number of operations of the previous approach is sub-optimal. For example, the array which has all (except last) leading zeroes: [0, 0, 0, ..., 0, 1].How many write operations to the array? For the previous approach, it writes 0's n-1n1 times, which is not necessary. We could have instead written just once. How? ..... By only fixing the non-0 element,i.e., 1.

    The optimal approach is again a subtle extension of above solution. A simple realization is if the current element is non-0, its' correct position can at best be it's current position or a position earlier. If it's the latter one, the current position will be eventually occupied by a non-0 ,or a 0, which lies at a index greater than 'cur' index. We fill the current position by 0 right away,so that unlike the previous solution, we don't need to come back here in next iteration.

    In other words, the code will maintain the following invariant:

    1. All elements before the slow pointer (lastNonZeroFoundAt) are non-zeroes.

    2. All elements between the current and slow pointer are zeroes.

    Therefore, when we encounter a non-zero element, we need to swap elements pointed by current and slow pointer, then advance both pointers. If it's zero element, we just advance current pointer.

    With this invariant in-place, it's easy to see that the algorithm will work.

    It is a great way to kown how to maintain two pointers, one pointer 'i' which is increase by for loop, another pointer 'pos' is increased by condition, which is if(nums[i] != 0).

  • 相关阅读:
    Vim
    一文搞定Samba云服务器配置(阿里云)CentOS8.3
    第四课 婴儿是如何思考的 思维的发展历程
    C++/VS基础篇
    Windows下Qt VS 打包程序 到他人电脑安装运行出现的问题
    第三课 斯金纳
    第二课基础 弗洛伊德
    C++中头文件和实现文件的关系
    字符串 数字 转换
    Ucore lab1实验报告
  • 原文地址:https://www.cnblogs.com/Answer1215/p/12000468.html
Copyright © 2011-2022 走看看