nums[i] != i + 1是判断正整数缺失的核心条件,因答案必在1到n+1间,理想排列应满足nums[i] == i + 1;交换需用while循环确保当前位稳定,仅当nums[i]∈[1,n]且目标位nums[i]-1≠i且无重复值时才交换,避免死循环与越界。

为什么nums[i] != i + 1是原地哈希的核心判断条件
因为题目要求找「第一个缺失的正整数」,而答案一定落在1到n+1之间(n为数组长度)。所以理想状态下,若数组能“自我排序”,就该满足:nums[0] == 1、nums[1] == 2、…、nums[i] == i + 1。一旦发现nums[i] != i + 1,且该位置无法通过交换修复(比如目标位置已存在正确值,或nums[i]根本不在[1, n]范围内),就说明i + 1缺失。
怎么写安全的元素交换循环,避免死循环和越界
关键在于每次只对当前下标i做一次有效交换,并确保不重复处理同一位置。常见错误是用for遍历完就结束,但交换后新来的数可能仍需继续归位——必须用while在每个i上反复尝试,直到当前位置稳定。
- 只交换满足条件的数:
nums[i]必须是1到n之间的正整数,且它想去的位置nums[i] - 1不能和当前i相同(否则已就位) - 必须检查目标位置是否已有相同值,否则会陷入
a↔b↔a死循环(例如[1,1]中第二个1试图换到index 0,但那里已是1) - 交换前校验
nums[i] - 1是否在[0, n-1]内,否则直接跳过(如nums[i] 或<code>nums[i] > n)
while (i = 1 && x <h3> <code>swap</code>之后<code>i</code>要不要自增</h3><p>不自增。因为交换后<code>nums[i]</code>换来了一个新值,它未必就位,必须立刻再次检查。只有当确认<code>nums[i]</code>已满足<code>== i + 1</code>,或根本不属于<code>[1,n]</code>范围(无法归位),才让<code>i++</code>。这也是为什么不能用<code>for (int i = 0; i 直接遍历——它强制推进,会漏掉刚换进来的待处理数。</code></p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master"><img src="https://img.php.cn/upload/skill/000/000/081/179051228971575.jpg" alt="C++ Code Review Master" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master" class="overflowclass">C++ Code Review Master</a> <p class="overflowclass">组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。</p> </div> <a rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div><h3>为什么最后扫描从<code>i = 0</code>开始找第一个<code>nums[i] != i + 1</code> </h3><p>因为原地哈希完成后,所有能归位的<code>1..n</code>都已各就各位;剩下的空缺必然出现在某个<code>i</code>处,对应缺失值就是<code>i + 1</code>。如果扫完整个数组都没找到,说明<code>1</code>到<code>n</code>全存在,那答案只能是<code>n + 1</code>。注意:这个结论依赖于前面交换逻辑的完备性——没把不该归位的数(如负数、超大数)强行塞进位置,否则会污染判断。</p><p>最容易被忽略的是边界校验顺序:<code>x != nums[x - 1]</code>必须放在<code>x >= 1 && x 之后,否则<code>x - 1</code>可能为负或越界,引发未定义行为。</code></p>
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










