1. 程式人生 > 其它 >LeetCode 0041 First Missing Positive

LeetCode 0041 First Missing Positive

原題傳送門

1. 題目描述

2. Solution 1

1、思路分析
將給定的陣列恢復成下面的形式,如果陣列中包含了x in [1, N],那麼恢復後,陣列的第x-1個元素為x。在恢復後,陣列應當有[1, 2, ..., N]的形式,但其中有若干個位置上的數是錯誤的,每一個錯誤的位置就代表了一個缺失的正數。以[3, 4, -1, 1]為例,恢復後的陣列應當為[1, -1, 3, 4],遍歷一遍就可以知道缺失了哪些數字。
恢復方法:對陣列進行一次遍歷,對於遍歷到的數x = nums[i],如果x in [1, N],則x應該出現在陣列的x-1位置,因此交換nums[i]和nums[x - 1],這樣x就出現在了正確的位置。在完成交換後,新的nums[i]可能還在[1, N]的範圍內,需要繼續進行交換,直到x not in [1, N]。
注意到上面的方法可能會陷入死迴圈。如果nums[i]恰好與nums[x-1]相等,那麼就會無限交換下去。此時有nums[i]=x=nums[x-1],說明x已經出現在了正確的位置。因此,可以跳出迴圈,開始遍歷下一個數。

2、程式碼實現

package Q0099.Q0041FirstMissingPositive;

/*
  Put each number in its right place.
    For example:
    When we find 5, then swap it with A[4].
    At last, the first place where its number is not right, return the place + 1.
 */
public class Solution {
    public int firstMissingPositive(int[] nums) {
        for (int i = 0; i < nums.length; i++)
            while (nums[i] > 0 &&
                    nums[i] <= nums.length &&
                    nums[nums[i] - 1] != nums[i])  // nums[nums[i] - 1] == nums[i] 就是已經在正確的位置了
                swap(nums, i, nums[i] - 1);

        for (int i = 0; i < nums.length; i++)
            if (nums[i] != i + 1) return i + 1;

        return nums.length + 1;
    }

    private void swap(int[] nums, int i, int j) {
        int tem = nums[i];
        nums[i] = nums[j];
        nums[j] = tem;
    }
}

3、複雜度分析
時間複雜度: O(n)
空間複雜度: O(1)