LeetCode 283. Move Zeroes [two pointers]

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.

For example, given nums = [0, 1, 0, 3, 12], after calling your function, nums should be [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之后,把所有的数字都向前移动一位,通过了大部分测试用例,但是无法处理连零的问题,代码如下:

 1 class Solution {
 2 public:
 3     void moveZeroes(vector<int>& nums) {
 4         int size = nums.size();
 5         for(int i=0;i<size;i++)
 6         {
 7             if(nums[i]==0)
 8             {
 9                 for(int j=i+1;j<size;j++)
10                    nums[j-1]=nums[j];
11                 nums[size-1]=0;
12             }
13         }
14         
15     }
16 };

换个思路,遍历两遍向量,记录下来0的数量,将非零数字存入新的向量,最后再将0补进新的向量,时间空间复杂度均是O(n),代码如下:

 1 void moveZeroes(vector<int>& nums) {
 2     int n = nums.size();
 3 
 4     // Count the zeroes
 5     int numZeroes = 0;
 6     for (int i = 0; i < n; i++) {
 7         numZeroes += (nums[i] == 0);
 8     }
 9 
10     // Make all the non-zero elements retain their original order.
11     vector<int> ans;
12     for (int i = 0; i < n; i++) {
13         if (nums[i] != 0) {
14             ans.push_back(nums[i]);
15         }
16     }
17 
18     // Move all zeroes to the end
19     while (numZeroes--) {
20         ans.push_back(0);
21     }
22 
23     // Combine the result
24     for (int i = 0; i < n; i++) {
25         nums[i] = ans[i];
26     }
27 }

进一步优化,用两个指针,第一个指针记录最后一个非零元素应该在的位置,第二个指针负责遍历,遇见非零元素就把发赋值给第一个元素所在位置,然后第一个指针前进一个,第二次遍历则是把第一个指针到向量的末尾全部赋值为0。时间复杂度O(n),空间复杂度O(1);

 1 void moveZeroes(vector<int>& nums) {
 2     int lastNonZeroFoundAt = 0;
 3     // If the current element is not 0, then we need to
 4     // append it just in front of last non 0 element we found. 
 5     for (int i = 0; i < nums.size(); i++) {
 6         if (nums[i] != 0) {
 7             nums[lastNonZeroFoundAt++] = nums[i];
 8         }
 9     }
10     // After we have finished processing new elements,
11     // all the non-zero elements are already at beginning of array.
12     // We just need to fill remaining array with 0's.
13     for (int i = lastNonZeroFoundAt; i < nums.size(); i++) {
14         nums[i] = 0;
15     }
16 }

再优化操作方面,只遍历一遍,两个指针,思路同上,这次赋值变成交换位置,交换的次数为非零元素的个数

1 void moveZeroes(vector<int>& nums) {
2     for (int lastNonZeroFoundAt = 0, cur = 0; cur < nums.size(); cur++) {
3         if (nums[cur] != 0) {
4             swap(nums[lastNonZeroFoundAt++], nums[cur]);
5         }
6     }
7 }

 

posted @ 2017-11-23 22:06  皇家大鹏鹏  阅读(211)  评论(0编辑  收藏  举报