Leetcode:Move Zeroes

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode:Move Zeroes相关的知识,希望对你有一定的参考价值。

   题目大意:提供一个长度为n的整数数组nums,要求将所有元素0移动到数组尾部,其余元素按照原先先后顺序排列。要求使用原址,不允许额外分配空间。

  直接上代码:

 1 class Solution {
 2     public void moveZeroes(int[] nums) {
 3         int n = nums.length;
 4         int rpos = 0;
 5         int wpos = 0;
 6         while(rpos < n)
 7         {
 8             if(nums[rpos] == 0)
 9             {
10                 if(wpos < rpos)
11                 {
12                     wpos = rpos;
13                 }
14                 for(;wpos < n && nums[wpos] == 0; wpos++);
15                 if(wpos == n)
16                 {
17                     break;
18                 }    
19                 nums[rpos] = nums[wpos];
20                 nums[wpos] = 0;
21                 
22             }
23             rpos++;
24         }
25     }
26 }

  这里rpos遍历0到n,而wpos则指向rpos后第一个非0的下标。由于每次循环(for循环和while循环分开考虑)的时间复杂度均为O(1),且每次循环都会使得wpos或rpos增大,而且二者均不可能减少,故for和while循环最多各发生O(n)次,因此总的时间复杂度为O(n)*O(1)=O(n)。

  再说明这段代码的正确性。我们每次发现nums[rpos]为0时,都会将nums[rpos]与nums[wpos]进行交换,故之后nums[rpos]非0,而由于代码中rpos不断增大,故我们可以认为当一趟while循环结束时,所有小于rpos的下标i,都满足nums[i]不为0。而while循环在rpos或wpos超界的时间退出,rpos超界说明nums中不包含元素0,而wpos超界说明nums[rpos+1],...,nums[n-1]均为0,无论哪种情况我们都正确的将所有的0转移到了nums的尾部。最后还需要说明所有非零元素按照原来先后顺序排序,首先明确实际上每次循环做的事情都是寻找nums[i]之后第一个非0元素的nums[j],交换nums[i]和nums[j]。注意wpos之右的元素都是未被修改的,而每次取得都是wpos之后的第一个非0元素,因此我们写入nums[i]的元素和写入nums[i+1]的元素由于wpos的增加,必定会使得nums[i+1]中写入的元素在nums[i]中写入的元素之后,故依靠偏序关系的传递性何以得到对于任意nums[i]和nums[j],若i<j,则其重排后的顺序依旧。

以上是关于Leetcode:Move Zeroes的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode:Move Zeroes

[leetcode] Move Zeroes

[leetcode]Move Zeroes

[Leetcode] Move Zeros

[LeetCode] Move Zeroe

283. (Move Zeroes)移动零