題目
給你一個未排序的整數數組,請你找出其中沒有出現的最小的正整數。
示例 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速度慢