1. 三数之和问题解析
三数之和(3Sum)是LeetCode上经典的算法问题,题目要求在一个整数数组中找到所有不重复的三元组,使得这三个数之和等于零。这个问题看似简单,但想要高效解决却需要一些巧妙的思路和优化技巧。
提示:三数之和问题在面试中经常出现,因为它能很好地考察候选人对双指针技巧的掌握程度,以及对算法时间复杂度的优化能力。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 暴力解法及其局限性
2.1 最直观的暴力解法
最直接的思路是使用三重循环枚举所有可能的三元组:
java复制for (int i = 0; i < nums.length; i++) {
for (int j = i+1; j < nums.length; j++) {
for (int k = j+1; k < nums.length; k++) {
if (nums[i] + nums[j] + nums[k] == 0) {
// 添加到结果列表
}
}
}
}
这种解法的时间复杂度是O(n³),当n较大时(比如n=3000),计算量会达到数十亿次,显然无法在合理时间内完成。
2.2 暴力解法的问题
除了时间复杂度高之外,暴力解法还有两个主要问题:
- 无法自动处理重复的三元组
- 没有利用数组的有序性(如果先排序的话)
3. 优化思路:排序+双指针
3.1 排序的重要性
首先对数组进行排序,这带来了几个好处:
- 可以方便地跳过重复元素,避免结果中出现重复三元组
- 可以利用有序性进行指针移动优化
- 为双指针法创造条件
排序的时间复杂度是O(nlogn),相对于后续的优化,这个开销是可以接受的。
3.2 双指针法的核心思想
固定第一个数nums[i]后,问题就转化为在剩余数组中找出两个数,使它们的和等于-nums[i]。这时可以使用双指针法:
- 左指针left初始化为i+1
- 右指针right初始化为数组末尾
- 根据当前三数之和与0的关系移动指针:
- 和>0:right左移(减小总和)
- 和<0:left右移(增大总和)
- 和=0:记录结果并移动两个指针
