LeetCode 热题 100 精讲|逆向思维与原地哈希篇:找到所有数组中消失的数字 · 缺失的第一个正数 · 寻找重复数 · 移动零
2026/5/5 12:17:28 网站建设 项目流程

一、448. 找到所有数组中消失的数字

🔗题目链接:448. 找到所有数组中消失的数字 - 力扣(LeetCode)

📝题目描述
给你一个含n个整数的数组nums,其中nums[i]在区间[1, n]内。请你找出所有在[1, n]范围内但没有出现在数组中的数字,并以数组的形式返回结果。

示例
输入:nums = [4,3,2,7,8,2,3,1]
输出:[5,6]
解释:数组长度为 8,缺失的数字是 5 和 6。

🧠思路分析
核心技巧:原地哈希(利用数组下标标记)。因为数字范围恰好是[1, n],我们可以遍历数组,对于每个数x,将下标x-1处的数字加上n(或取负)作为标记。第二次遍历时,若某个下标位置的值没有被标记(即仍 ≤ n),则说明该下标对应的数字缺失。

步骤

  1. 第一次遍历:对于每个num,取idx = abs(num) - 1,将nums[idx]变为负数(表示idx+1这个数字出现过)。

  2. 第二次遍历:若nums[i] > 0,则i+1缺失。

💻代码实现(C++)

class Solution { public: vector<int> findDisappearedNumbers(vector<int>& nums) { int n = nums.size(); for (int i = 0; i < n; ++i) { int idx = abs(nums[i]) - 1; if (nums[idx] > 0) nums[idx] = -nums[idx]; // 标记为负数 } vector<int> res; for (int i = 0; i < n; ++i) { if (nums[i] > 0) res.push_back(i + 1); } return res; } };

📚相关学习资源

  • 文章:栈结构实战:从「有效括号」到「最小栈」,吃透栈的核心用法
    资源类型:CSDN(您提供的原样保留)
    核心亮点:通过有效括号这经典题讲解栈的核心特性,包含哈希表映射匹配、三种失败情况的详细分析。
    https://blog.csdn.net/2401_84526799/article/details/160534738

  • 文章:讲解LeetCode第20题:有效的括号(完整代码)
    资源类型:腾讯云开发者社区 · 2025-12-17 发布
    核心亮点:提供完整的 C++ 代码实现,包含unordered_map哈希表映射、栈操作(push/pop/top/empty)的详细代码片段解释,适合对照学习。

复杂度分析

  • 时间复杂度:O(n)

  • 空间复杂度:O(1)(不计输出数组)


二、41. 缺失的第一个正数

🔗题目链接:41. 缺失的第一个正数 - 力扣(LeetCode)

📝题目描述
给你一个未排序的整数数组nums,请你找出其中没有出现的最小的正整数。请实现时间复杂度O(n)且只使用常数级别额外空间的解决方案。

示例
输入:nums = [3,4,-1,1]
输出:2
解释:1 出现,2 缺失。

🧠思路分析
同样使用原地哈希:我们要将数字x放到下标x-1的位置(前提是1 ≤ x ≤ n)。遍历数组,如果当前数字在[1, n]范围内且不在正确位置,就把它交换到正确的位置。第二次遍历,第一个nums[i] != i+1的位置就是答案。

💻代码实现(C++)

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; } };

📚相关学习资源

  • 文章:栈结构实战:从「有效括号」到「最小栈」,吃透栈的核心用法
    资源类型:CSDN(您提供的原样保留)
    核心亮点:双栈法(主栈 + 辅助栈)完整实现,详细介绍如何使getMin达到 O(1),辅助栈同步记录每个状态下的最小值。
    https://blog.csdn.net/2401_84526799/article/details/160534738

  • 文章:【LeetCode 热题100】155:最小栈(详细解析)(Go语言版)
    资源类型:阿里云开发者社区 · 2025-05-21 发布
    核心亮点:辅助栈法完整实现,提供 push 时同步更新、pop 时检查是否需要弹出辅助栈顶的详细操作说明,还介绍了单栈 + 差值记录法的进阶思路及常见易错点总结。
    https://developer.aliyun.com/article/1664042

复杂度分析

  • 时间复杂度:O(n),每个数字最多交换一次。

  • 空间复杂度:O(1)


三、287. 寻找重复数

🔗题目链接:287. 寻找重复数 - 力扣(LeetCode)

📝题目描述
给定一个包含n + 1个整数的数组nums,其中数字都在[1, n]范围内。可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。要求不能修改数组,且只能使用常数级别的额外空间。

示例
输入:nums = [1,3,4,2,2]
输出:2

🧠思路分析
经典的Floyd 判圈算法(快慢指针)。将数组视为链表,nums[i]表示从inums[i]的指针。因为存在重复数字,所以链表一定有环,环的入口就是重复的数。

步骤

  1. 快慢指针:slow = nums[0]fast = nums[nums[0]],直到相遇。

  2. 寻找入口:slow = 0,再与fast同步走,相遇点即为答案。

💻代码实现(C++)

class Solution { public: int findDuplicate(vector<int>& nums) { int slow = nums[0]; int fast = nums[nums[0]]; while (slow != fast) { slow = nums[slow]; fast = nums[nums[fast]]; } slow = 0; while (slow != fast) { slow = nums[slow]; fast = nums[fast]; } return slow; } };

📚相关学习资源

  • 文章:栈的经典应用:字符串解码 & 每日温度 深度解析
    资源类型:CSDN(2026-04-14 发布)
    核心亮点:栈在「嵌套结构处理」场景下的标杆题目,通过四步遍历分析法(数字 push、[入栈、]弹出处理、字母拼接)完整拆解嵌套解码逻辑。
    https://blog.csdn.net/2401_84526799/article/details/160124186

  • 文章:力扣热题 394:字符串解码(详细解析)(Go语言版)
    资源类型:阿里云开发者社区 · 2025-03-24 发布
    核心亮点:提供栈解法和递归解法两种实现,栈解法通过维护数字栈与字符串栈依次处理[],递归解法利用函数调用逐层解析嵌套结构,两者时间复杂度均为 O(n)。
    https://developer.aliyun.com/article/1658590

复杂度分析

  • 时间复杂度:O(n)

  • 空间复杂度:O(1)


四、283. 移动零

🔗题目链接:283. 移动零 - 力扣(LeetCode)

📝题目描述
给定一个数组nums,编写一个函数将所有0移动到数组的末尾,同时保持非零元素的相对顺序。请就地操作,不能复制数组。

示例
输入:[0,1,0,3,12]
输出:[1,3,12,0,0]

🧠思路分析
双指针:快慢指针。slow指向下一个非零元素应该放置的位置,fast遍历数组。当fast遇到非零时,交换nums[slow]nums[fast],然后slow++。这样所有非零元素就会按顺序移到前面,零被推到后面。

💻代码实现(C++

class Solution { public: void moveZeroes(vector<int>& nums) { int slow = 0; for (int fast = 0; fast < nums.size(); ++fast) { if (nums[fast] != 0) { swap(nums[slow], nums[fast]); slow++; } } } };

📚相关学习资源

  • 文章:栈的经典应用:字符串解码 & 每日温度 深度解析
    资源类型:CSDN(2026-04-14 发布)
    核心亮点:栈在「单调栈」场景下的标杆题目,通过“当天温度高于栈顶温度则弹出记录”的核心逻辑拆解单调栈实现过程。
    https://blog.csdn.net/2401_84526799/article/details/160124186

  • 文章:【LeetCode 热题100】739:每日温度(详细解析)(Go语言版)
    资源类型:阿里云开发者社区 · 2025-05-19 发布
    核心亮点:单调递减栈实现,栈中存索引,遇到比栈顶温度高时弹出并计算天数差,提供 Go 语言实现和复杂度分析(O(n))。
    https://developer.aliyun.com/article/1663755

复杂度分析

  • 时间复杂度:O(n)

  • 空间复杂度:O(1)


结语

逆向思维与原地哈希的四道题,核心在于利用已有的数组空间进行标记或交换,从而在 O(1) 额外空间内解决问题:

  • 消失的数字:利用负数标记。

  • 缺失的第一个正数:置换到正确位置。

  • 寻找重复数:快慢指针判环。

  • 移动零:双指针交换。

这些技巧是面试中的高频考点,务必熟练掌握。

下一篇预告:LeetCode 热题 100 精讲|滑动窗口篇:无重复字符的最长子串 · 找到字符串中所有字母异位词 · 最小覆盖子串 · 滑动窗口最大值,持续更新连载。


免责声明

本文仅供学习交流与算法思路分享,内容基于作者个人理解及公开资料整理。所有题目链接、资源文档均来源于互联网,版权归原作者所有。文章中的代码已在常见环境下验证,但不同环境或版本可能导致结果差异,请读者自行测试并谨慎参考。如有疑问或版权问题,请联系作者处理。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询