持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第5天,点击查看活动详情
41. 缺失的第一个正数
示例 1:
输入:nums = [1,2,0]
输出:3
示例 2:
输入:nums = [3,4,-1,1]
输出:2
示例 3:
输入:nums = [7,8,9,11,12]
输出:1
提示:
1 <= nums.length <= 5 * 105
-2^31 <= nums[i] <= 2^31 - 1
思路
首先,题目要求的是最小的未出现的正整数,就相当于求一个 mex(nums)的东西嘛
那么,我们这个数据范围给的是 ,那么,负数和零都是干扰项嘛!
根本不干涉我们的行动,在我们眼里面,和正无穷大没有任何区别
首先,我们将所以的负数给处理为一个远超过本题范围的"魔数"
其次,我们再来关心本体所存在的问题,找到最小的那个数。
这个题有点意思,和我前面写过的一道题类似,用来哈希的思想
前面那道题在这里
有兴趣可以去看那道题,更详细
这里简单介绍一下这种思想:
我当前这个数,若是在 的范围内,那么,我们可以把当前这个数交换道对于位置上去
什么意思呢?
形如这种: 原来是: ,现在变成
实现了对换操作,每一次,都会交换到对应的元素上去一个元素,即总交换次数不超过
因为每次交换完至少会有一个位置被安排上自己的数,然后下次就是另外一个数安排到对应位置上
最后,我们就可以清楚的知道了 在 [1, n] 中到底差哪个数了!
什么?你问大于 n 的数如何处理
需要处理么?
补充,若是[1, n] 都出现过,那么必定是 n + 1
代码
class Solution {
public:
int firstMissingPositive(vector<int>& nums) {
int n = nums.size();
const int INF = 0x3f3f3f3f;
for_each(begin(nums), end(nums), [&](auto& a) {
if (a <= 0) a = INF;
});
auto compare = [&](int x) {
return x >= 1 && x <= n;
};
for (int i = 1; i <= n; i ++) {
while (compare(nums[i-1]) && nums[i-1] != nums[nums[i-1]-1])
swap(nums[i-1], nums[nums[i-1]-1]);
}
for (int i = 1; i <= n; i ++)
if (nums[i-1] != i) return i;
return n+1;
}
};