[LeetCode] 41. First Missing Positive(第一个缺失的正数)
- Difficulty: Hard
- Related Topics: Array
- Link: https://leetcode.com/problems/first-missing-positive/
Description
Given an unsorted integer array nums
, find the smallest missing positive integer.
给定一无序整数数组 nums
,找到其缺失的最小正数。
Follow up
Could you implement an algorithm that runs in O(n)
time and uses constant extra space?
你能否以 \(O(N)\) 时间复杂度,并消耗常数额外空间解答此题?
Examples
Example 1
Input: nums = [1,2,0]
Output: 3
Example 2
Input: nums = [3,4,-1,1]
Output: 2
Example 3
Input: nums = [7,8,9,11,12]
Output: 1
Constraints
0 <= nums.length <= 300
-2^31 <= nums[i] <= 2^31 - 1
Hints
-
Think about how you would solve the problem in non-constant space. Can you apply that logic to the existing space?
想想如果没有常数空间限制,你会如何解题。你能将这个逻辑应用到常数空间的解法上吗? -
We don't care about duplicates or non-positive integers
我们不考虑重复的数,以及非正数。 -
Remember that O(2n) = O(n)
注意:\(O(2N) = O(N)\)
Solution
这题如果没有常数空间限制,还是很容易的:准备一个长度和 nums
相同的 boolean 数组。遍历 nums
,如果 num
在 nums
的索引范围内,则将对应位置为 true
,最后找这个 boolean 数组里第一个 false
出现的位置,代码如下:
class Solution {
fun firstMissingPositive(nums: IntArray): Int {
val visited = BooleanArray(nums.size)
for (num in nums) {
if ((num - 1) in visited.indices) {
visited[num - 1] = true
}
}
val result = visited.indexOfFirst { !it }
return if (result == -1) {
nums.size + 1
} else {
result + 1
}
}
}
如果不使用额外空间,那就得在原数组上进行改动了。这个解法也不难,总结起来就一句话:把数移动到正确的位置(nums[i] = i + 1
)。经过如此操作后,第一个位置不对的数的下标即为所求。代码如下:
class Solution {
fun firstMissingPositive(nums: IntArray): Int {
for (i in nums.indices) {
while (nums[i] in 1..nums.size && nums[nums[i] - 1] != nums[i]) {
nums.swap(i, nums[i] - 1)
}
}
for (i in nums.indices) {
if (nums[i] != i + 1) {
return i + 1
}
}
return nums.size + 1
}
private fun IntArray.swap(i: Int, j: Int) {
val t = this[i]
this[i] = this[j]
this[j] = t
}
}