直接遍历比二分更合适,因数组虽有序但需动态统计缺失正整数个数,遍历中维护curr和missing即可直观求解,避免二分的预处理与重复计算。

为什么直接遍历比二分更合适
这个问题表面看像二分搜索题(毕竟数组有序、要找第N个缺失值),但实际用二分需要额外预处理或反复计算缺失数量,反而绕远。直接遍历 nums 数组,边走边数“当前已覆盖到哪个正整数”,是最直观、不易错的方式。
关键点在于:缺失数只出现在正整数序列中,而 nums 是升序非负整数数组(可能含 0 或重复值)。我们真正关心的是从 1 开始的连续正整数流里,哪些没被 nums 覆盖。
- 跳过所有 ≤ 0 的数(
nums[i] ) - 跳过重复值(
nums[i] == nums[i-1]) - 对每个有效正整数
nums[i],检查它是否等于当前期望的最小未出现正整数curr;如果相等,curr++;如果不等且大于curr,说明[curr, nums[i]-1]全部缺失
怎么边遍历边累计缺失数
设 curr = 1 表示当前待匹配的最小正整数,missing = 0 记录已找到的缺失数个数。每遇到一个有效的 nums[i]:
- 若
nums[i] == curr:匹配成功,curr++ - 若
nums[i] > curr:说明curr缺失,missing++;若missing == n,直接返回curr;否则curr++,继续判断是否仍 - 若
nums[i] :跳过(重复或更小值,已处理过)
示例:nums = [1,2,4,5], n = 2。初始 curr=1, missing=0 → 1==1 → curr=2;→ 2==2 → curr=3;→ 4>3 → missing=1, curr=4;→ 4==4 → curr=5;→ 5==5 → curr=6;遍历完,missing=1 ,所以第 2 个缺失数是 <code>curr + (n - missing) - 1 = 6 + 1 - 1 = 6。
遍历结束还没凑够 N 个怎么办
这是最容易漏掉的边界:数组扫完了,但只找到了 k 个缺失数。此时,剩余缺失数一定在 <code>curr 及之后的连续正整数中——因为 curr 是数组能覆盖到的“最远连续起点”+1。
所以最终答案就是:curr + (n - missing) - 1。注意不是 curr + n,因为 curr 本身就算第 1 个候选缺失数。
- 例如
nums = [1,2,3], n = 2:遍历后curr = 4, missing = 0,答案是4 + 2 - 1 = 5 - 再如
nums = [2,3,4], n = 3:第一个数2 > 1,立刻得missing = 1, curr = 2;接着2 == 2→curr = 3;…… 最终curr = 5, missing = 1,答案是5 + 2 - 1 = 6
C++ 实现时要注意的细节
别忘了 nums 可能为空,或全为负数/零——这时 curr 始终是 1,答案就是 n。
另外,循环中比较 nums[i] 和 curr 时,必须先判 i ,否则越界;跳过重复值时,要用 <code>i > 0 && nums[i] == nums[i-1],而不是 i > 0 && nums[i] == nums[i-1](没错,这句写两遍是提醒你容易手抖写错下标)。
核心逻辑不依赖 STL 算法,纯 while + if 就够了,避免引入 std::lower_bound 增加理解成本和边界调试负担。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











