Given an unsorted integer array, find the smallest missing positive integer.
Example 1:
Input: [1,2,0]
Output: 3
Example 2:
Input: [3,4,-1,1]
Output: 2
Example 3:
Input: [7,8,9,11,12]
Output: 1
Note: Your algorithm should run in O(n)
time and uses constant extra space.
題意:找到一個無序的數組中不存在的最小的正整數。
思路1: 和 的差別比較小,可以用下面的方法矇混過關。先排序,後去重,然後從小往大搜索,忽視非正數。
代碼1: 時間和常量空間。
class Solution {
public:
int firstMissingPositive(vector<int>& nums) {
sort(nums.begin(), nums.end());
int len = unique(nums.begin(), nums.end()) - nums.begin(), p = 1;
for (int i = 0; i < len; ++i) {
if (nums[i] <= 0) continue;
else if (nums[i] == p) ++p;
else break;
}
return p;
}
};
思路2:如果用額外的空間做的話,可以用整數哈希表,從 1
開始,能過的話,是 時間。但是下面的——發現不可能開這樣大的空間,即使用 bitset
,比如 [2147483647]
。
class Solution {
public:
int firstMissingPositive(vector<int>& nums) {
bitset<20000> bst;
for (const auto &i : nums)
if (i > 0)
bst.set(i);
int i = 1;
while (bst[i]) ++i;
return i;
}
};
不過這裏其實是一時糊塗,除了 <=0
的數外,完全可以拒絕大於數組長度的數,然後將其他的數所指向的位置的 bitset
置 1
。最後檢查即可。
代碼2如下,在上面的代碼中做了一點小修改:
class Solution {
public:
int firstMissingPositive(vector<int>& nums) {
bitset<10000> bst;
for (const auto &i : nums)
if (i > 0 && i <= nums.size())
bst.set(i);
int i = 1;
while (bst[i]) ++i;
return i;
}
};
還有能過的是使用 unordered_set
,此時不用在乎數據範圍。代碼如下:
class Solution {
public:
int firstMissingPositive(vector<int>& nums) {
unordered_set<int> st;
for (const auto &i : nums) st.insert(i);
int i = 1;
while (st.find(i) != st.end()) ++i;
return i;
}
};
效率:
執行用時:0 ms, 在所有 C++ 提交中擊敗了100.00% 的用戶
內存消耗:6.9 MB, 在所有 C++ 提交中擊敗了100.00% 的用戶
思路3:既然題目說可以在 和不使用額外空間的情況下得到答案,那麼只有一種可能,即使用原數組。我們忽視負數、0
、超出數組長度範圍的數(說明它們不是答案),則把另外的數,它們指向的數組位置做標記——不可能取負(以前有的題目可以,但是這裏不可以)或置零——排除這些途徑,唯一的方法就是把這些數交換回原來的位置上。
交換的方法也有一定的技巧:
- 從頭檢查起,如果發現一個數
> 0 && <= nums.size() && nums[i] != nums[nums[i] - 1]
,就將其與nums[nums[i] - 1]
(爲了容納等於數組長度的那個正數) 交換;此時仍指向i
的位置,繼續對這個值實施上面的過程;直到現在的nums[i]
已經處於正確位置或屬於逃票——票號<= 0
,或>=
最大座位號,則終止交換; - 然後對
i+1,i+2
位置的元素做同樣的操作。
然後,我們從 1
位置開始檢查,發現值和位置+1不匹配,就返回這個位置的下標+1;如果都匹配,則返回數組長度+1。
其實,這種做法看提示應該能夠想得出來。
Think about how you would solve the problem in non-constant space. Can you apply that logic to the existing space?
We don’t care about duplicates or non-positive integers.
Remember that O(2n) = O(n).
代碼3:
class Solution {
public:
int firstMissingPositive(vector<int>& nums) {
int n = nums.size();
for (int i = 0; i < n; ++i)
while (nums[i] > 0 && nums[i] <= n && nums[i] != nums[nums[i] - 1])
swap(nums[i], nums[nums[i] - 1]);
for (int i = 0; i < n; ++i)
if (nums[i] != i + 1)
return i + 1;
return n + 1;
}
};
效率:
執行用時:0 ms, 在所有 C++ 提交中擊敗了100.00% 的用戶
內存消耗:6.3 MB, 在所有 C++ 提交中擊敗了100.00% 的用戶