LeetCode 448 Find All Numbers Disappeared in an Array


Problem:

Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.

Find all the elements of [1, n] inclusive that do not appear in this array.

Could you do it without extra space and in O(n) runtime? You may assume the returned list does not count as extra space.

Example:

Input:
[4,3,2,7,8,2,3,1]

Output:
[5,6]

Summary:

長度為n的整形數組a中的所有數大於等於1,小於等於n,其中可能包含重復兩次的數字。

輸出[1, n]中不存在於數組a中的數字集合。

Solution:

1. 首先想到的方法是用map創建Hash表,key為數組中出現的數字,value為出現次數,再尋找哪個數字出現0次。

 1 class Solution {
 2 public:
 3     vector<int> findDisappearedNumbers(vector<int>& nums) {
 4         int len = nums.size(), maxNum = -1;
 5         sort(nums.begin(), nums.end());
 6         map<int, int> m;
 7         vector<int> res;
 8         
 9         for (int i = 0; i < len; i++) {
10             m[nums[i]]++;
11             maxNum = maxNum < nums[i] ? nums[i] : maxNum;
12         }
13         
14         for (int i = 1; i <= len; i++) {
15             if (!m[i]) {
16                 res.push_back(i);
17             }
18         }
19         
20         return res;
21     }
22 };

但題目中要求不開數組標記,故這個方法不可行。

2. 不消耗其余空間的做法,首先想到的是將數組排序,用一個變量k記錄下一個需要查找的[1, n]中的數字,將不存在於數組中的數字存下來。

需要注意的出現重復數字時的處理。

 1 class Solution {
 2 public:
 3     vector<int> findDisappearedNumbers(vector<int>& nums) {
 4         int len = nums.size();
 5         sort(nums.begin(), nums.end());
 6         vector<int> res;
 7         
 8         int k = 1;
 9         for (int i = 0; i < len; i++) {
10             if (k != nums[i]) {
11                 while (k < nums[i]) {
12                     res.push_back(k++);
13                 }
14             }
15             
16             if (i < len - 1 && nums[i] == nums[i + 1]) {
17                 i++;
18             }
19             
20             k++;
21         }
22         
23         while (k <= len) {
24             res.push_back(k++);
25         }
26         
27         return res;
28     }
29 };

但因為有排序,時間復雜度為O(nlogn),不滿足題目中的O(n),故這種方法仍不可行。

3. 由於題目中有數組中所有數字都大於等於1且小於等於n,而n為數組長度這一條件。所以可以以數組下標作為索引標記哪些數字出現過,標記方法為將出現數字對應下標的數字標為負數。

  1. 計算出數組中出現的數字x的下標形式,則下表為index = |x| - 1,可將數組a中得a[index]標為負數來標記數字x出現在數組中
  2. 若數組中某數字已為負數,說明該數字在數組中出現過
  3. 最終遍歷數組,若a[i]為正數,表明數字 i + 1在數組中沒有出現過。

這種方法僅遍歷兩次數組即可完成,切不用消耗其余空間。

 1 class Solution {
 2 public:
 3     vector<int> findDisappearedNumbers(vector<int>& nums) {
 4         int len = nums.size();
 5         vector<int> res;
 6         for (int i = 0; i < len; i++) {
 7             int index = abs(nums[i]) - 1;
 8             if (nums[index] > 0) {
 9                 nums[index] *= -1;
10             }
11         }
12         
13         for (int i = 0; i < len; i++) {
14             if (nums[i] > 0) {
15                 res.push_back(i + 1);
16             }
17         }
18         
19         return res;
20     }
21 };

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM