1. 三数之和问题解析
今天我们来聊聊LeetCode Hot 100中的经典题目——三数之和(3Sum)。这道题在算法面试中出现频率极高,也是很多初学者容易踩坑的典型题目。我曾在实际面试中多次遇到这道题的变种,也见过不少候选人在这里栽跟头。
三数之和问题的核心是:给定一个包含n个整数的数组nums,判断nums中是否存在三个元素a、b、c,使得a + b + c = 0?找出所有满足条件且不重复的三元组。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 暴力解法与优化思路
2.1 直观的暴力解法
最直接的思路就是三层循环遍历所有可能的三元组组合:
python复制def threeSum(nums):
result = []
n = len(nums)
for i in range(n):
for j in range(i+1, n):
for k in range(j+1, n):
if nums[i] + nums[j] + nums[k] == 0:
triplet = sorted([nums[i], nums[j], nums[k]])
if triplet not in result:
result.append(triplet)
return result
这种解法的时间复杂度是O(n³),在n较大时(比如n=3000)会非常慢,完全无法通过LeetCode的测试用例。
2.2 排序+双指针优化
更高效的解法是先对数组排序,然后使用双指针技巧:
- 首先对数组进行排序(O(nlogn))
- 固定一个数nums[i],然后在剩下的数组中使用双指针寻找两个数,使得三者之和为0
- 跳过重复元素以避免重复解
python复制def threeSum(nums):
nums.sort()
result = []
n = len(nums)
for i in range(n-2):
if i > 0 and nums[i] == nums[i-1]:
continue # 跳过重复元素
left, right = i+1, n-1
while left < right:
total = nums[i] + nums[left] + nums[right]
if total < 0:
left += 1
elif total > 0:
right -= 1
else:
result.append([nums[i], nums[left], nums[right]])
# 跳过重复元素
while left < right and nums[left] == nums[left+1]:
left += 1
while left < right and nums[right] == nums[right-1]:
right -= 1
left += 1
right -= 1
return result
这种解法的时间复杂度是O(n²),空间复杂度是O(1)(不考虑结果存储空间)。
3. 关键细节与边界条件
3.1 去重处理
去重是三数之和问题中最容易出错的部分。我们需要在三个地方进行去重:
- 外层循环固定数nums[i]的去重
- 找到解后左指针的去重
- 找到解后右指针的去重
注意:去重判断应该是nums[i] == nums[i-1]而不是nums[i] == nums[i+1],否则会漏掉一些解。
3.2 提前终止条件
当固定数nums[i] > 0时,由于数组已排序,后面的数都大于0,三数之和不可能为0,可以直接终止循环:
python复制if nums[i] > 0:
break
3.3 小优化技巧
- 数组长度小于3时直接返回空结果
- 固定数nums[i]后,最小可能的三数之和如果大于0,可以提前终止
- 最大可能的三数之和如果小于0,可以跳过当前固定数
4. 常见错误与调试技巧
4.1 典型错误案例
- 忘记排序数组
- 去重逻辑错误(如使用nums[i] == nums[i+1])
- 双指针移动逻辑错误(如找到解后只移动一个指针)
- 边界条件处理不当(如数组长度小于3)
4.2 调试建议
- 先用小规模测试用例验证(如[0,0,0]、[-1,0,1,2,-1,-4])
- 打印中间变量(如每次循环的i、left、right值)
- 特别注意去重逻辑是否正确
5. 复杂度分析与变种问题
5.1 时间复杂度分析
- 排序:O(nlogn)
- 外层循环:O(n)
- 内层双指针:O(n)
总体时间复杂度:O(n²)
5.2 空间复杂度
如果不考虑存储结果的空间,算法本身只需要常数级别的额外空间:O(1)
5.3 相关变种问题
- 最接近的三数之和(3Sum Closest)
- 四数之和(4Sum)
- 较小的三数之和(3Sum Smaller)
- 三数之和的各种变种(如要求乘积为某个值等)
6. 实际应用场景
三数之和算法虽然看起来是纯算法题,但在实际中有不少应用:
- 数据分析中寻找特定组合
- 金融领域的三因子分析
- 游戏开发中的碰撞检测
- 密码学中的某些算法
7. 个人解题心得
在实际解决这个问题时,我有几点深刻体会:
- 排序是这类问题的关键第一步,能大大简化后续处理
- 双指针技巧在有序数组中非常高效
- 去重逻辑需要特别小心,最好用具体例子验证
- 边界条件往往比主逻辑更容易出错
我建议初学者可以先用暴力解法实现,确保理解题意,然后再逐步优化。在面试中,即使不能立即想到最优解,也应该先提出暴力解法,再和面试官讨论优化方向。
