1. 程式人生 > 其它 >LeetCode-41 缺失的第一個正整數

LeetCode-41 缺失的第一個正整數

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/first-missing-positive

題目描述

給你一個未排序的整數陣列 nums ,請你找出其中沒有出現的最小的正整數。

請你實現時間複雜度為 O(n) 並且只使用常數級別額外空間的解決方案。
 

示例 1:

輸入:nums = [1,2,0]
輸出:3
示例 2:

輸入:nums = [3,4,-1,1]
輸出:2
示例 3:

輸入:nums = [7,8,9,11,12]
輸出:1
 

提示:

1 <= nums.length <= 5 * 105
-231 <= nums[i] <= 231

- 1

 

解題思路

理論上並不存在時間複雜度為O(n) 空間複雜度為 O(1)的演算法來做這道題,所以需要藉助題目提供的nums來解,nums的範圍為n,那麼可以利用nums來判斷1-n中是否有數字出現,如果沒有,那麼最小正整數為n+1,否則就是第一個缺失的數字。

一個思路是利用負號來記錄1-n中數字是否出現過,先將所有負數變成n+1,然後遍歷,如果數字x出現就將數字x對應的下標x-1的值設定為負數,等結束後第一個正數的下標加一就是缺失的數字。

另一個思路是重置歸位,將1-n中的數字重置到nums對應的位置上並且繼續重置被交換的數,那麼第一個錯位的數字就是缺失的數字。注意由於nums中數字可能相同,所以交換的雙方相等就可以結束交換繼續遍歷。

程式碼展示

負號做標記

class Solution {
public:
    int firstMissingPositive(vector<int>& nums) {
        int n = nums.size();
        for(int i = 0; i < n; i++)
        {
            if(nums[i] <= 0)
                nums[i] = n + 1;
        }
        for(int i = 0; i < n; i++)
        {
            
if(abs(nums[i]) < n + 1) nums[abs(nums[i]) - 1] = nums[abs(nums[i]) - 1] < 0 ? nums[abs(nums[i]) - 1] : -1 * nums[abs(nums[i]) - 1]; } for(int i = 0; i < n; i++) if(nums[i] > 0) return i + 1; return n + 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 + 1 && 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;
    }
}; 

 

執行結果