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的主要内容,如果未能解决你的问题,请参考以下文章