Leetcode:NO.41 缺失的第一個正數 哈希表

題目

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

示例 1:

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

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

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

你的算法的時間複雜度應爲O(n),並且只能使用常數級別的額外空間。

鏈接:https://leetcode-cn.com/problems/first-missing-positive

解題記錄

  • 通過構建數組用來存儲出現過的正整數,因爲一個長度爲n的數組中未出現的正整數不可能大於n+1,因此需要的是一個長度爲n+2的數組,+2是因爲還有0
  • 將數組範圍出現過的數值記錄,通過遍歷記錄數組第一個false即是沒有出現的最大正整數
  • 如果爲空的話直接返回1
  • 這種方法未滿足空間要求
/**
 * @author ffzs
 * @describe
 * @date 2020/6/27
 */
public class Solution {
    public static int firstMissingPositive(int[] nums) {
        boolean[] tmp = new boolean[nums.length+2];
        for (int num : nums) {
            if (num > 0 && num <= nums.length) {
                tmp[num] = true;
            }
        }
        for (int i = 1; i < tmp.length; i++) {
            if(!tmp[i]) return i;
        }
        return 1;
    }

    public static void main(String[] args) {
        int[] num = {1};
        System.out.println(firstMissingPositive(num));
    }
}

在這裏插入圖片描述

  • 可以通過排序之後遍歷
  • 如果大於res直接返回res因爲res就是最小
  • 如果有res就+1
  • 但是因爲排序的話時間並不滿足題目要求
/**
 * @author ffzs
 * @describe
 * @date 2020/6/27
 */
public class Solution2 {
    public static int firstMissingPositive(int[] nums) {
        Arrays.sort(nums);
        int res = 1;
        for (int num : nums) {
            if (num > res) return res;
            else if (num == res) res++;
        }
        return res;
    }

    public static void main(String[] args) {
        int[] num = {1};
        System.out.println(firstMissingPositive(num));
    }
}

看似這種算法中途可以跳出感覺是快,但是熟不知,排序的時候數組已經摸過一遍了,浪費了時間,所以慢一些,具體慢多少還要看選擇的排序方法
在這裏插入圖片描述

進階

  • 第一個方法中因爲用了新的數組,因此沒有滿足空間複雜度的要求
  • 因此我們需要想一個方法直接使用原數組進行信息的記錄
  • 因爲最小爲出現正整數不可能大於len,我們可以將nums中小於等於len這部分數進行標記,最直接的方法就是變成負數,通過判斷第一個不是負數的即可
  • 但是又一個問題就是有的數值本身就是負數,要排除掉這部分的影響
  • 因爲這部分負數直接不影響對最終值的判斷,那麼直接把這部分值通過範圍以外的任何數代替即可
/**
 * @author ffzs
 * @describe
 * @date 2020/6/27
 */
public class Solution3 {
    public static int firstMissingPositive(int[] nums) {
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] <= 0) nums[i] = nums.length + 1;
        }
        for (int i = 0; i < nums.length; i++) {
            int num = Math.abs(nums[i]);
            if (num <= nums.length){
                nums[num-1] = -Math.abs(nums[num-1]);
            }
        }
        for (int i = 0; i < nums.length; i++) {
            if(nums[i] > 0) return i+1;
        }
        return nums.length + 1;
    }

    public static void main(String[] args) {
        int[] num = {3, 4, -1, 1};
        System.out.println(firstMissingPositive(num));
    }
}

在這裏插入圖片描述

可見如果排序是通過快速排序logN的話速度不一定比循環兩次的2N速度慢

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