【每日一題】LeetCode. 41.缺失的第一個正數

每日一題,防止癡呆 = =

一、題目大意

給你一個未排序的整數數組,請你找出其中沒有出現的最小的正整數。
在這裏插入圖片描述
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/first-missing-positive

二、題目思路以及AC代碼

思路:

這題標定的難度是困難,但我感覺思路並不是很難想到。

首先第一個想法肯定是可以用哈希表做的,或者標記數組,這樣我們只需要用O(N)額外的空間就可以達到時間複雜度爲O(N)的要求了。

題目明確要求不能用額外的空間,而且時間複雜度要求爲O(N),這也是標記難度爲困難的原因。但是我們可以順着這個思路,再結合題目特點考慮一下。首先要求最小的沒有出現的正整數,對於長度爲N的數組來說,結果只能是 1 ~ N + 1中的一個數,這樣的話,我們其實只需要知道數組中 1 ~ N 這些數出現的情況就可以了,而要知道 1 ~ N 這些數出現的情況,只需要一個長度爲 N 的標記數組即可,題目正好是一個長度爲N的空間,那麼我們就想到可以裏用原數組空間去統計數組中 1 ~ N 這些數的出現情況。

具體操作我舉個例子解釋一下:
原數組: [-1,4,2,1,9,10],長度爲 6

首先遍歷 -1,因爲 -1 <= 0 跳過;
然後遍歷 4,因爲 0 < 4 <= 6,所以暫存4的值;
然後找到nums[4 - 1]的位置,存儲的是 1,因爲 0 < 1 <= 6,所以暫存1的值,將1位置處改爲 -MAX_INT,原數組變爲 [-1, 4, 2, -MAX_INT, 9, 10];
然後找到nums[1 - 1]的位置,存儲的是-1,因爲 -1 <= 0,所以不存 -1 的值,將-1位置處改爲-MAX_INT,原數組變爲[-MAX_INT, 4, 2, -MAX_INT, 9, 10];
繼續遍歷2,因爲 0 < 2 <= 6,所以暫存2的值;
然後找到nums[2 - 1]的位置,存儲的是 4,因爲 0 < 4 <= 6,所以暫存4的值,將4位置處改爲-MAX_INT,原數組變爲[-MAX_INT, -MAX_INT, 2, -MAX_INT, 9, 10];
然後找到nums[4 - 1]的位置,存儲的是-MAX_INT,則跳過;
繼續遍歷-MAX_INT,跳過;
繼續遍歷9,由於 9 > 6,跳過;
繼續遍歷10,由於 10 > 6,跳過;

最終得到結果數組爲 [-MAX_INT, -MAX_INT, 2, -MAX_INT, 9, 10],其中 0,1,3 索引處爲-MAX_INT,正好標記了1,2,4三個元素,然後在遍歷找到第一個不爲-MAX_INT的元素即是結果。

但是這樣實現有一個小問題,就是標記元素-MAX_INT要找一個在原數組中沒有出現的數字才能得到正確的結果。

AC代碼
#define MAX_INT -2147483648

class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        int n_size = nums.size();

        for (int i=0;i<n_size;i++) {
            if (nums[i] <= 0 || nums[i] > n_size) continue;

            int idx = nums[i] - 1;
            int temp = nums[idx];
            nums[idx] = MAX_INT;
            idx = temp;

            while (idx > 0 && idx <= n_size) {
                temp = nums[idx - 1];
                nums[idx - 1] = MAX_INT;
                idx = temp;
            }
        }

        for (int i=0;i<n_size;i++) {
            if (nums[i] != MAX_INT) return i + 1;
        }
        
        return n_size + 1;
    }
};

如果有問題,歡迎大家指正!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章