资讯动态

三数之和算法解析:双指针优化与面试技巧

发布时间:2026/8/24 5:43:45 来源:尧图企业网站定制
1. 题目背景与核心考察点三数之和3Sum是LeetCode题库中编号15的经典题目长期位列各大科技公司面试高频题库Top 10。这道题看似简单——给定一个包含n个整数的数组nums判断nums中是否存在三个元素a、b、c使得a b c 0但实际上它考察了面试者对多重算法思想的综合运用能力。这道题之所以被归类为T1级别最高优先级主要因为它在实际面试中出现频率极高。根据2023年LeetCode官方统计该题在Amazon、Microsoft、Google三家公司的面试中出现概率分别达到42%、38%和35%。题目同时考察了以下几个核心能力对暴力解法的优化意识时间复杂度从O(n³)降到O(n²)双指针技巧的灵活运用边界条件与去重处理的严谨性空间复杂度的控制能力提示虽然题目描述允许直接返回数值但面试官通常会要求返回所有不重复的三元组这使得去重逻辑成为重要的考察点之一。2. 暴力解法与初步优化2.1 三重循环的原始解法最直观的解法是使用三重循环枚举所有可能的三元组def threeSum(nums): n len(nums) res [] for i in range(n): for j in range(i1, n): for k in range(j1, n): if nums[i] nums[j] nums[k] 0: res.append([nums[i], nums[j], nums[k]]) return res这种解法的时间复杂度为O(n³)在LeetCode上提交会导致超时当n3000时操作次数达到27亿次。但它是理解问题本质的起点。2.2 哈希表优化思路我们可以将第三层循环转化为哈希查找def threeSum(nums): nums.sort() res [] n len(nums) for i in range(n): for j in range(i1, n): target - (nums[i] nums[j]) if target in nums[j1:]: triplet [nums[i], nums[j], target] if triplet not in res: res.append(triplet) return res这样时间复杂度降为O(n²)但依然存在两个问题in操作在列表中的时间复杂度是O(n)去重方式效率低下列表的not in操作也是O(n)3. 双指针最优解法3.1 算法框架与排序预处理真正的优化来自于排序双指针的组合策略def threeSum(nums): nums.sort() # 关键步骤先排序 res [] n len(nums) for i in range(n-2): # 留出两个位置给左右指针 if i 0 and nums[i] nums[i-1]: # 跳过重复元素 continue left, right i1, n-1 while left right: total nums[i] nums[left] nums[right] if total 0: left 1 elif total 0: right - 1 else: res.append([nums[i], nums[left], nums[right]]) # 跳过重复元素 while left right and nums[left] nums[left1]: left 1 while left right and nums[right] nums[right-1]: right - 1 left 1 right - 1 return res3.2 关键步骤解析排序预处理时间复杂度O(nlogn)这是后续优化的基础使相同的数字相邻便于去重使双指针移动有方向性左增右减外层循环固定第一个数nums[i]跳过i的重复值nums[i] nums[i-1]提前终止条件如果nums[i] 0可以直接break因为数组已排序双指针扫描left从i1开始right从末尾开始根据三数之和与0的关系移动指针和0需要更大的数 → left右移和0需要更小的数 → right左移和0记录结果并跳过重复值3.3 时间复杂度分析排序O(nlogn)外层循环O(n)内层双指针O(n)总体O(nlogn) O(n²) O(n²)4. 边界条件与易错点4.1 特殊输入处理# 输入长度不足3 if len(nums) 3: return [] # 全零特殊情况 if all(num 0 for num in nums): return [[0, 0, 0]] if len(nums) 3 else []4.2 去重逻辑的三种实现方式结果集去重不推荐if triplet not in res: res.append(triplet)时间复杂度高可能超时哈希表去重中等推荐res set() res.add(tuple(sorted([nums[i], nums[j], nums[k]]))) return list(map(list, res))指针跳跃去重最优解 如前面代码所示在找到有效三元组后while left right and nums[left] nums[left1]: left 1 while left right and nums[right] nums[right-1]: right - 14.3 常见错误案例忘记处理输入为空或长度不足3的情况去重时只跳过一个重复值应用while循环而非if移动指针时越过边界需保持left right未考虑整数溢出Python无此问题但其他语言需注意5. 变种题目与扩展思考5.1 最接近的三数之和LeetCode 16def threeSumClosest(nums, target): nums.sort() n len(nums) closest float(inf) for i in range(n-2): left, right i1, n-1 while left right: total nums[i] nums[left] nums[right] if abs(total - target) abs(closest - target): closest total if total target: left 1 elif total target: right - 1 else: return target return closest5.2 四数之和LeetCode 18def fourSum(nums, target): def kSum(nums, target, k): res [] if not nums: return res avg target // k if avg nums[0] or nums[-1] avg: return res if k 2: return twoSum(nums, target) for i in range(len(nums)): if i 0 or nums[i] ! nums[i-1]: for subset in kSum(nums[i1:], target-nums[i], k-1): res.append([nums[i]] subset) return res def twoSum(nums, target): res [] left, right 0, len(nums)-1 while left right: total nums[left] nums[right] if total target or (left 0 and nums[left] nums[left-1]): left 1 elif total target or (right len(nums)-1 and nums[right] nums[right1]): right - 1 else: res.append([nums[left], nums[right]]) left 1 right - 1 return res nums.sort() return kSum(nums, target, 4)5.3 实际工程应用场景金融风控系统中的异常交易检测多因素组合分析游戏开发中的碰撞检测优化三维空间位置关系电商推荐系统中的组合优惠计算化学分子式中的原子组合验证6. 记忆要点与面试技巧6.1 五分钟快速记忆模板def threeSum(nums): nums.sort() res [] n len(nums) for i in range(n-2): if i 0 and nums[i] nums[i-1]: continue left, right i1, n-1 while left right: total nums[i] nums[left] nums[right] if total 0: left 1 elif total 0: right - 1 else: res.append([nums[i], nums[left], nums[right]]) while left right and nums[left] nums[left1]: left 1 while left right and nums[right] nums[right-1]: right - 1 left 1 right - 1 return res6.2 面试应答策略先沟通确认输入输出要求是否允许重复返回索引还是数值分步骤先描述暴力解法提出排序双指针优化思路重点强调去重逻辑写代码按照模板快速实现注意变量命名规范测试用[0,0,0,0]、[-1,0,1,2,-1,-4]等案例验证分析明确说出时间/空间复杂度6.3 性能优化极限对于特别大的输入n10^5可以考虑并行化处理将数组分块后多线程计算提前终止当nums[i]0时直接break使用更快的排序算法如C的sort我在实际面试中遇到的一个变形题是要求返回所有满足条件的三元组索引而非数值此时需要注意不能先排序会打乱原始索引需要使用哈希表记录原始位置去重逻辑变得更复杂需要比较值的组合

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价