41. 缺失的第一个正数

题目描述

思路
这是一道 LeetCode 当中的 Hard 题目。
最开始我的思路是使用一个集合来对数组当中的非负数进行一道统计,再对这个集合进行遍历,以寻找出其中缺失的第一个正数。但是这算法需要额外建立一个集合类型的数据结构。
参考了 LeetCode 的题解,我发现可以使用nums数组本身作为集合,来对数组当中的非负数进行统计。
具体来说,对于数组当中的负数,它们对答案没有任何贡献,直接让它们的值转为n + 1即可,其中n为数组的长度;
其次,对于数组当中的非负数,我们判断一次它的值是否在[0, n - 1]之间,如果在的话,就将num这个数值对应的下标num - 1的值标记为负数,可以直接使用-abs(num - 1);如果不在的话,则它对答案没有贡献,因为最坏的情况下缺失的第一个正数只能是n + 1。
最后,我们对整理好后的nums数组进行遍历,如果发现nums[i] > 0,则说明当前位置对应的整数i + 1就是缺失的第一个正数,此时返回i + 1即可。如果对nums进行遍历之后并未发现符合条件的数值,则返回n + 1。
基于以上思路,我们写代码来解决问题。
Golang 题解
go
func abs(x int) int {
if x < 0 {
return -x
}
return x
}
func firstMissingPositive(nums []int) int {
n := len(nums)
// 将负数的值赋为 n + 1, 这样它们就被排除在哈希表之外了.
for i := 0; i < n; i ++ {
if nums[i] <= 0 {
nums[i] = n + 1
}
}
// 如果当前数的绝对值在 [0, n] 之间, 那么就将其加入到哈希表当中.
for i := 0; i < n; i ++ {
num := abs(nums[i])
if num <= n {
nums[num - 1] = -abs(nums[num - 1])
}
}
for i := 0; i < n; i ++ {
if nums[i] > 0 {
return i + 1
}
}
return n + 1
}
Python 题解
python
class Solution:
def firstMissingPositive(self, nums: List[int]) -> int:
n = len(nums)
for i in range(0, n):
if nums[i] <= 0:
nums[i] = n + 1
for i in range(0, n):
num = abs(nums[i])
if num <= n:
nums[num - 1] = -abs(nums[num - 1])
for i in range(0, n):
if nums[i] > 0:
return i + 1
return n + 1