1. 程式人生 > >LeetCode解題思路:27. Remove Element

LeetCode解題思路:27. Remove Element

and ext int 過程 順序 for sta all tex

  Given an array and a value, remove all instances of that value in place and return the new length.Do not allocate extra space for another array, you must do this in place with constant memory. The order of elements can be changed. It doesn‘t matter what you leave beyond the new length.

Example:
  Given input array nums

= [3,2,2,3], val = 3 Your function should return length = 2, with the first two elements of nums being 2.

題意:給出一個數組和一個值,原地挖掉數組中對應的值(以下以val代替),不允許使用新數組即空間復雜度O(1),返回長度並返回去掉val後的數組

錯誤思路:

  只看到了返回值,我開始的時候真的只看到了返回值。然後根本沒去除掉val。所以最快去掉所有val並返回長度才是關鍵。

基本思路:

  如果不會特別的思路,就用一種比較慢的想法做也可以,每遇到一個val就把後面所有元素向前移動一位把val覆蓋掉,並且讓數組長度減1,如果val在最後一位那麽數組長度直接減1。最壞情況時間復雜度O(n*n)。因為數據量比較小所以即使反復的對數據進行操作也不會特別慢。

 1 int removeElement(int* nums, int numsSize, int val) {
 2     int i=0, j =i+1;
 3     for(i=0;i<numsSize; ++i){
 4         if(nums[i] == val ){
 5             if(i<numsSize - 1){
 6                 for(j = i+1;j<numsSize;++j){
 7                     nums[j-1] = nums[j];
 8                 }
9 --i; 10 } 11 --numsSize; 12 } 13 } 14 return numsSize; 15 }

  稍微優化一下,其實我們根本不在乎數組中除了val以外數字的順序,所以我們可以遇到val時就把最後一個元素賦值給當前元素,然後數組長度減1。最後返回數組長度即可。最差時間復雜度O(n)。

 1 int removeElement(int* nums, int numsSize, int val) {   
 2     int i=0;
 3     while(i<numsSize){
 4         if(nums[i] == val){
 5             if(i != numsSize - 1){
 6                 nums[i] = nums[numsSize - 1];
 7             }
 8             --numsSize;
 9         }else{
10             ++i;
11         }
12     }
13     return numsSize;
14 }

  再優化一下,第三種方法,不見得比第二種好,但是代碼至少看上去更短。

1 class Solution {
2 public:
3     int removeElement(vector<int>& nums, int val) {
4         nums.erase(remove(nums.begin(),nums.end(),val),nums.end());
5         return nums.size();
6     }
7 };

  使用了STL中的erase(remove())組合。底層實現其實有點像第二種,大致是如下,比如我們想刪除容器中的99:

    技術分享

  如果我們把remove的返回值存放在一個叫做newEnd的新叠代器中,那麽remove後應該就是這樣的:

    技術分享

  而中間的過程,3個99被放在了尾部,用問號代替?然而實際上裏面的元素是這樣的:

    技術分享

  真實的移動情況是這樣的:

    技術分享

  找到一個待覆蓋位置,用後面第一個非val元素覆蓋,則該位置變為新待覆蓋位置,然後重復前面操作,直到最後一個元素,返回第一個待覆蓋元素位置。

  這樣做的好處在於不會改變數組中其他元素順序並且時間復雜度較第一種方法要低(因為每次只查找少於n-i個元素,移動其中1個元素)。

  實現代碼略。

LeetCode解題思路:27. Remove Element