把值 x 放到下标 x-1,最后第一个 a[i] != i+1 即答案,O(n) 时间 O(1) 空间。
OJ: leetcodecn
题目 ID: first-missing-positive
难度:提高+/省选-
标签:数组哈希表cpppython
日期: 2026-07-28 22:05
题意
未排序整数数组,找出其中没有出现的最小的正整数。要求 O(n) 时间、O(1) 额外空间。
思路
排序 O(n log n) 不够快。核心观察:答案一定在 [1, n+1] 范围内。把值 x 放到下标 x-1 的位置(类似原地哈希),然后扫描第一个下标和值不匹配的位置。
- 只关注
[1, n]的值,超出范围的不管。 - 用 swap 循环放置,每个值至多被交换一次。
代码
cpp
/**
* Author by Rainboy
*/
// main.cpp:把值 x 放到下标 x-1,第一个 a[i] != i+1 即答案,O(n)。
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
int firstMissingPositive(vector<int> &nums) {
int n = nums.size();
for (int i = 0; i < n; i++) {
while (nums[i] >= 1 && nums[i] <= n && nums[nums[i] - 1] != nums[i])
swap(nums[i], nums[nums[i] - 1]);
}
for (int i = 0; i < n; i++)
if (nums[i] != i + 1)
return i + 1;
return n + 1;
}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<int> a(n);
for (int &x : a)
cin >> x;
cout << Solution().firstMissingPositive(a) << '\n';
return 0;
}python
#!/usr/bin/env python3
from typing import List
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]:
x = nums[i] - 1
nums[i], nums[x] = nums[x], nums[i]
for i in range(n):
if nums[i] != i + 1:
return i + 1
return n + 1
def main() -> None:
n = int(input())
nums = list(map(int, input().split()))
print(Solution().firstMissingPositive(nums))
if __name__ == "__main__":
main()复杂度
- 时间复杂度:O(n),每个元素至多被交换一次。
- 空间复杂度:O(1),原地交换。
总结
"值域与下标映射"是 O(1) 空间哈希的常用手法。利用出题范围 [1, n] 把数组本身当作哈希表。