先聊聊为什么这道题值一百题复盘。两数之和是LeetCode上提交量最高、最像"算法世界入口"的一道题,但说实话,很多人刷到几十题之后就把它忘了——毕竟它只是第一题,简单得不像话。我刷到第一百题的时候回头重做了一遍,才发现当初只是把答案背下来,并没有真正理解这道题背后牵出的哈希表、时间空间权衡、以及边界处理这些贯穿整个算法学习的核心主线。
这篇文章不是单纯给你一个可以AC的题解,而是站在刷完一百题之后的位置,重新拆解这道题的三层解法演进、哈希表的本质逻辑、变体题目的延伸方向,以及复盘一百题过程中我自己踩过的一些真实坑。适合刚开始刷题、正在刷前200题、或者刷到一定数量但觉得"记不住、不会举一反三"的读者。
1. 为什么第一百题复盘选了两数之和:这道题的地位被严重低估了
先说一个反直觉的现象:两数之和虽然标着"简单",是无数人打开LeetCode之后做的第一道题,但它在整个算法题体系里的位置,远比它的难度标签要重要得多。它是哈希表在面试题里最高频的开场,也是几乎所有"查找类问题"的最小原型。
1.1 两数之和在LeetCode题库里的真实位置
两数之和的题号是1,这个编号本身就说明了它在题库中的地位。从统计上看,它是被提交次数最多的题目之一,被各大公司的面试题库反复收录,也是许多刷题计划里的第一个节点。它不像后面的LRU缓存、滑动窗口最大值那样上来就给你一个复杂的工程结构,而是用最简单的数学表达——数组里找两个数,让它们的和等于目标值——把"查找"这一核心操作塞到你面前。
正因为它简单,大多数人看一眼题目,用双层循环跑一次,AC了,然后就走了。但实际上,这道题的升级路径可以延伸出三数之和、四数之和、两数之和II(输入有序数组)、两数之和III(设计类)、以及后面那些更复杂的子数组和等于K的问题。每一道看起来全新的题目,底层都在复用它那套"用哈希表记录历史信息"的思路。
1.2 一百题之后再重做,我发现当初根本没读懂题
说实话,我第一次做两数之和的时候,就是暴力解跑通的,连哈希表的解法都是看了题解才写的。这其实说明了一个问题:AC不代表理解,跑通不代表掌握。我刷到第一百题时再回头做它,看到的是完全不同的画面——这道题玩来玩去就两个关键点:第一个是"你需不需要保留数组的原始顺序信息",第二个是"你要返回下标还是返回值"。这两个点决定了你会选哪条路,也决定了你在后续几道变体题里会不会卡住。
比如,如果题目改成"输入有序数组",那最优解就不是哈希表了,而是双指针,时间复杂度O(n)、空间复杂度O(1),比哈希表的空间开销更优。再比如,如果要求返回所有不重复的组合,那哈希表就很难处理"去重"这件事,排序加双指针才是常规解法。你看,同一种数学关系,因为输出要求的变化,解法体系完全不同。这才是这道题复盘价值所在。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 从暴力到哈希:两数之和的三层解法演进
先上一段题目的完整定义:给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出和为目标值 target 的那两个整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案,但是数组中同一个元素不能使用两遍。
这题解法上的演进,本质上是一条"如何减少不必要的遍历"的思考路径。
2.1 暴力枚举:所有解法里最"老实"的一版
暴力解法的思路不需要任何额外存储:从头到尾固定第一个数,然后在它后面剩下的区间里找第二个数,逐个相加判断。
python复制def twoSum_brute(nums, target):
n = len(nums)
for i in range(n):
for j in range(i
