1. 程式人生 > >[LeetCode] First Missing Positive 首個缺失的正數

[LeetCode] First Missing Positive 首個缺失的正數

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.

這道題讓我們找缺失的首個正數,由於限定了O(n)的時間,所以一般的排序方法都不能用,最開始我沒有看到還限制了空間複雜度,所以想到了用HashSet來解,這個思路很簡單,第一遍遍歷陣列把所有的數都存入HashSet中,並且找出陣列的最大值,下次迴圈從1開始遞增找數字,哪個數字找不到就返回哪個數字,如果一直找到了最大的數字,則返回最大值+1,程式碼如下:

解法一:

// NOT constant space
class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        int mx = 0;
        unordered_set<int> s;
        for (int num : nums) {
            if (num <= 0) continue;
            s.insert(num);
            mx = max(mx, num);
        }
        
for (int i = 1; i <= mx; ++i) { if (!s.count(i)) return i; } return mx + 1; } };

但是上面的解法不是O(1)的空間複雜度,所以我們需要另想一種解法,既然不能建立新的陣列,那麼我們只能覆蓋原有陣列,我們的思路是把1放在陣列第一個位置nums[0],2放在第二個位置nums[1],即需要把nums[i]放在nums[nums[i] - 1]上,那麼我們遍歷整個陣列,如果nums[i] != i + 1, 而nums[i]為整數且不大於n,另外nums[i]不等於nums[nums[i] - 1]的話,我們將兩者位置調換,如果不滿足上述條件直接跳過,最後我們再遍歷一遍陣列,如果對應位置上的數不正確則返回正確的數,程式碼如下:

解法二:

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[nums[i] - 1] != nums[i]) {
                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;
    }
};

類似題目:

參考資料: