这题的做法可太多了,且都是 1 m s 1ms 1ms 内跑完,不同的就是时间和空间复杂度,代码从上至下越来越难想到
JAVA
① 排序 + 二分法 【时间复杂度: O ( N l o g N + N l o g N ) O(NlogN+NlogN) O(NlogN+NlogN) 空间复杂度: O ( 1 ) O(1) O(1)】
import java.util.Arrays;
class Solution {
public int firstMissingPositive(int[] nums) {
if (nums.length == 0)
return 1;
Arrays.sort(nums);
for (int i = 1; i <= nums.length; i++) {
int tmp = binarySearch(nums, i);
if (tmp == -1)
return i;
}
return nums.length + 1;
}
public int binarySearch(int[] nums, int target) {
int i = 0;
int j = nums.length - 1;
while (i <= j) {
int mid = (i + j) / 2;
if (nums[mid] == target)
return mid;
else if (nums[mid] < target)
i = mid + 1;
else
j = mid - 1;
}
return -1;
}
}
② 排序 【时间复杂度: O ( N l o g N + N ) O(NlogN+N) O(NlogN+N) 空间复杂度: O ( N ) O(N) O(N)】
import java.util.Arrays;
class Solution {
public int firstMissingPositive(int[] nums) {
int min = 1;
Arrays.sort(nums);
for (int i = 0; i < nums.length; i++) {
if (nums[i] == min)
min++;
}
return min;
}
}
③ 哈希表【时间复杂度: O ( N + N ) O(N+N) O(N+N) 空间复杂度: O ( N ) O(N) O(N)】
import java.util.HashSet;
import java.util.Set;
class Solution {
public int firstMissingPositive(int[] nums) {
Set<Integer> hashset = new HashSet<>();
for (int num : nums) {
hashset.add(num);
}
for (int i = 1; i <= nums.length; i++) {
if (!hashset.contains(i))
return i;
}
return nums.length + 1;
}
}
④ 置换【时间复杂度: O ( N + N ) O(N+N) O(N+N) 空间复杂度: O ( 1 ) O(1) O(1)】
public class Solution {
public int firstMissingPositive(int[] nums) {
int len = nums.length;
for (int i = 0; i < len; i++) {
// 若两个位置的值不一样
while (nums[i] > 0 && nums[i] <= len && nums[i] != nums[nums[i] - 1])
swap(nums, i, nums[i] - 1);
}
for (int i = 0; i < len; i++) {
if (nums[i] != i + 1)
return i + 1;
}
return len + 1;
}
private void swap(int[] nums, int n, int m) { //类型用 public或者 private都行
int tmp = nums[n];
nums[n] = nums[m];
nums[m] = tmp;
}
}
⑤ 原地哈希【时间复杂度: O ( N + N + N ) O(N+N+N) O(N+N+N) 空间复杂度: O ( 1 ) O(1) O(1)】
class Solution {
public int firstMissingPositive(int[] nums) {
int len = nums.length;
for (int i = 0; i < len; i++) {
if (nums[i] <= 0) {
nums[i] = len + 1; // 负数变成 n+1
}
}
for (int i = 0; i < len; i++) {
int tmp = Math.abs(nums[i]);
if (tmp <= len) {
nums[tmp - 1] = -Math.abs(nums[tmp - 1]); // 对应位置的值变负数
}
}
for (int i = 0; i < len; i++) {
if (nums[i] > 0) // 对应位置的值不是负数,该位置值即最小正数值
return i + 1;
}
return len + 1;
}
}
Python
① set 集合(40ms)
class Solution:
def firstMissingPositive(self, nums: List[int]) -> int:
if not nums:
return 1
setn = set(nums)
for i in range(1, len(nums)+1):
if (i not in setn):
return i
return len(nums)+1
② heapq 堆(44ms)
class Solution:
def firstMissingPositive(self, nums: List[int]) -> int:
import heapq # heapq只能保证 nums[0]永远是最小的元素
heapq.heapify(nums) # 将列表转换为堆
if not nums:
return 1
min = 1
while nums and nums[0] <= min:
if nums[0] == min:
min += 1
heapq.heappop(nums)
return min
③ 原地哈希(40ms)
class Solution:
def firstMissingPositive(self, nums: List[int]) -> int:
n = len(nums)
for i in range(n):
if nums[i] <= 0:
nums[i] = n + 1
for i in range(n):
num = abs(nums[i])
if num <= n:
nums[num - 1] = -abs(nums[num - 1])
for i in range(n):
if nums[i] > 0:
return i + 1
return n + 1
④ 置换(32ms)
class Solution:
def firstMissingPositive(self, nums: List[int]) -> int:
n = len(nums)
for i in range(n):
while 1 <= nums[i] <= n and nums[nums[i] - 1] != nums[i]:
nums[nums[i] - 1], nums[i] = nums[i], nums[nums[i] - 1] # 相当于 swap
for i in range(n):
if nums[i] != i + 1:
return i + 1
return n + 1