1. 程式人生 > >Leetcode演算法Java全解答--41. 缺失的第一個正數

Leetcode演算法Java全解答--41. 缺失的第一個正數

Leetcode演算法Java全解答–41. 缺失的第一個正數

文章目錄

題目

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

說明:
你的演算法的時間複雜度應為O(n),並且只能使用常數級別的空間。

示例

示例 1:

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

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

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

想法

  1. 錯了!使用二進位制來儲存,將第N位的資料改成1,原來想的有二十億資料,後面發現int只有32位,只能保證32個,錯了

  2. 交換法

將1放到陣列 索引0位置,將2放到陣列 索引1的位置,將3放到陣列索引1的位置

假設交換的資料還是大於0且小於i+1,則放在合適的位置,且資料不相等,避免死迴圈

用的是 if判斷 加上 i–,別人的方法使用while迴圈

然後去迴圈陣列,資料不對就返回

結果

超過97%的測試案例

時間複雜度/空間複雜度:O(n)/1

總結

// TODO

程式碼

我的答案

public int firstMissingPositive(int[] nums) {

    if (nums.length == 0) {
        return 1;
    }

    for (int i = 0; i < nums.length; i++) {
        if (nums[i] > 0) {
            // 假設交換的資料還是大於0且<i+1,則放在合適的位置,且資料不相等,避免死迴圈
            if (nums[i] < nums.length + 1 && nums[i] != nums[nums[i] - 1]) {
                int tmp = nums[nums[i] - 1];
                nums[nums[i] - 1] = nums[i];
                nums[i] = tmp;
                i--;
            }
        }
    }

    // 然後去迴圈陣列,資料不對就返回
    for (int i = 0; i < nums.length; i++) {
        if (i + 1 != nums[i]) {
            return i + 1;
        }
    }
    return nums.length + 1;
}


/**
     * 位運算,錯誤答案
     * @param nums
     * @return
     */
    public int bit(int[] nums) {
        long bitNum = 0;
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] > 0) {
                // 將bitNum的第nums[i]變為1
                // 第 i 位與0 或,值不變。第 i 位與1 或,變成1。因此,我們的目標是 num 與 一個第 i 位值為1,其它位的值都為0的數相 或
                bitNum = bitNum | (1 << nums[i]);
            }
        }

        for (int i = 1; i < nums.length + 1; i++) {
            boolean zeroBit = (bitNum & (1 << i)) == 0;
            if (zeroBit) {
                return i;
            }
        }

        return nums.length + 1;
    }

大佬們的答案

/**************************************
 * 比我好的答案 better
 * ***********************************/
public int better(int[] nums) {
    int n = nums.length;
    for (int i = 0; i < n; i++) {
        while (nums[i] > 0 && nums[i] <= n && nums[nums[i] - 1] != nums[i]) {
            int temp = nums[nums[i] - 1];
            nums[nums[i] - 1] = nums[i];
            nums[i] = temp;
        }
    }

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

測試用例

@Test
public void test041() {
    // 建立測試案例
    int[] test1 = new int[] { 0, 1, 2 };
    int[] test2 = new int[] { 10, 4, 16, 54, 17, -7, 21, 15, 25, 31, 61, 1, 6, 12, 21, 46, 16, 56, 54, 12, 23, 20,
            38, 63, 2, 27, 35, 11, 13, 47, 13, 11, 61, 39, 0, 14, 42, 8, 16, 54, 50, 12, -10, 43, 11, -1, 24, 38,
            -10, 13, 60, 0, 44, 11, 50, 33, 48, 20, 31, -4, 2, 54, -6, 51, 6 };
    int[] test3 = new int[] { 0, 1, 2, 3, 5 };
    int[] test4 = new int[] { 2 };

    // 測試案例期望值
    int expResult1 = 3;
    int expResult2 = 3;
    int expResult3 = 4;
    int expResult4 = 1;

    Solution041 solution041 = new Solution041();

    int result1 = solution041.firstMissingPositive(test1);
    int result2 = solution041.firstMissingPositive(test2);
    int result3 = solution041.firstMissingPositive(test3);
    int result4 = solution041.firstMissingPositive(test4);

    Assert.assertEquals(expResult1, result1);
    Assert.assertEquals(expResult2, result2);
    Assert.assertEquals(expResult3, result3);
    Assert.assertEquals(expResult4, result4);
}

其他

程式碼託管碼雲地址:https://gitee.com/lizhaoandroid/LeetCodeAll.git

檢視其他內容可以點選專欄或者我的部落格哈:https://blog.csdn.net/cmqwan

“大佬們的答案” 標籤來自leetcode,侵權請聯絡我進行刪改

如有疑問請聯絡,聯絡方式:QQ3060507060