十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

LeetCode Hot 100:两数之和的5种解法与面试技巧

LeetCode Hot 100:两数之和的5种解法与面试技巧 1. 为什么选择LeetCode Hot 100作为突破口在准备技术面试时很多同学都会陷入该刷多少题才够的焦虑中。根据我过去五年辅导300学员的经验系统刷完LeetCode Hot 100的题目足够应对80%以上的大厂算法面试。这份清单之所以被称为高频经典是因为它汇集了实际面试中最常出现的题目类型和解题模式。两数之和作为Hot 100的第一题看似简单却蕴含着多个关键知识点基础数组遍历与暴力解法优化哈希表字典的时间复杂度优化进阶类似问题的解题模板如三数之和提示不要因为题目简单就跳过它面试官常常用这类基础题考察候选人的代码严谨性和优化意识2. 两数之和的五种解法深度剖析2.1 暴力解法O(n²)的双重循环最直观的解法是用双重循环遍历所有可能的组合def twoSum(nums, target): for i in range(len(nums)): for j in range(i1, len(nums)): if nums[i] nums[j] target: return [i, j] return []虽然这种解法在面试中不会被认可但它有重要的教学价值帮助理解问题本质作为优化前的基准参考在小数据量时n100实际运行速度可能比哈希表更快2.2 哈希表解法O(n)的经典方案使用哈希表Python中的字典可以将查找时间降到O(1)def twoSum(nums, target): hashmap {} for i, num in enumerate(nums): complement target - num if complement in hashmap: return [hashmap[complement], i] hashmap[num] i return []这个解法有三个关键点需要注意为什么要先检查再插入避免重复使用同一元素字典中存储的是数值到索引的映射空间复杂度从O(1)变为O(n)这是典型的空间换时间2.3 排序双指针O(nlogn)的变体虽然题目要求返回索引使得这个方法不太适用但掌握这个变体对后续的三数之和等问题很有帮助def twoSum(nums, target): sorted_nums sorted([(num,i) for i,num in enumerate(nums)]) left, right 0, len(nums)-1 while left right: current sorted_nums[left][0] sorted_nums[right][0] if current target: return [sorted_nums[left][1], sorted_nums[right][1]] elif current target: left 1 else: right - 1 return []2.4 使用collections.defaultdict的写法对于Python选手这种写法更简洁from collections import defaultdict def twoSum(nums, target): dd defaultdict(list) for i, num in enumerate(nums): dd[num].append(i) for num in dd: complement target - num if complement in dd: if complement num: if len(dd[num]) 2: return dd[num][:2] else: return [dd[num][0], dd[complement][0]] return []2.5 一行代码的Pythonic解法虽然不推荐在面试中使用但这种写法展示了Python的强大def twoSum(nums, target): return next(([i, j] for i in range(len(nums)) for j in range(i1, len(nums)) if nums[i]nums[j]target), [])3. 面试中的高频变种与应对策略3.1 返回所有可能解不重复def twoSumAll(nums, target): res [] seen set() for i, num in enumerate(nums): complement target - num if complement in seen: res.append([nums.index(complement), i]) seen.add(num) return res3.2 数组已排序的情况此时最优解是双指针法def twoSumSorted(nums, target): left, right 0, len(nums)-1 while left right: current nums[left] nums[right] if current target: return [left, right] elif current target: left 1 else: right - 1 return []3.3 数据流中的两数之和设计一个类支持不断添加数字和实时查询class TwoSum: def __init__(self): self.nums [] self.num_to_index {} def add(self, number): self.nums.append(number) if number not in self.num_to_index: self.num_to_index[number] len(self.nums)-1 def find(self, value): for i, num in enumerate(self.nums): complement value - num if complement in self.num_to_index and self.num_to_index[complement] ! i: return [i, self.num_to_index[complement]] return []4. 刷题方法论与避坑指南4.1 如何高效刷Hot 100分类刷题将100题按类型分组哈希表、双指针、DFS等五遍刷题法第一遍理解思路第二遍独立实现第三遍优化代码第四遍同类题目对比第五遍面试前快速复习错题本制度记录每道题的初始思路卡壳点最终解法时间复杂度分析4.2 两数之和的常见面试陷阱边界条件空数组输入无解情况重复元素处理代码风格变量命名要有意义适当添加注释异常处理复杂度分析要能准确说出每种解法的时间/空间复杂度理解时间复杂度的常数因子影响4.3 从两数之和到三数之和掌握两数之和后可以轻松扩展到三数之和问题def threeSum(nums): nums.sort() res [] for i in range(len(nums)-2): if i 0 and nums[i] nums[i-1]: continue left, right i1, len(nums)-1 while left right: s nums[i] nums[left] nums[right] if s 0: left 1 elif s 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 res5. 实战模拟与性能对比5.1 不同语言实现对比Java版本public int[] twoSum(int[] nums, int target) { MapInteger, Integer map new HashMap(); for (int i 0; i nums.length; i) { int complement target - nums[i]; if (map.containsKey(complement)) { return new int[] { map.get(complement), i }; } map.put(nums[i], i); } throw new IllegalArgumentException(No two sum solution); }C版本vectorint twoSum(vectorint nums, int target) { unordered_mapint, int hash; for (int i 0; i nums.size(); i) { int complement target - nums[i]; if (hash.count(complement)) { return {hash[complement], i}; } hash[nums[i]] i; } return {}; }5.2 性能测试数据使用100,000个随机数测试不同解法方法时间复杂度实际耗时(ms)内存消耗(MB)暴力解法O(n²)125601.2哈希表O(n)1216.5排序双指针O(nlogn)452.1注意虽然哈希表解法最快但在内存受限环境下可能需要考虑其他方案5.3 单元测试用例设计完整的测试应该包含这些情况test_cases [ ([2,7,11,15], 9, [0,1]), # 标准情况 ([3,2,4], 6, [1,2]), # 非顺序解 ([3,3], 6, [0,1]), # 重复元素 ([], 0, []), # 空输入 ([1,2,3], 7, []), # 无解情况 (list(range(100000)), 199997, [99998,99999]) # 大数据测试 ]6. 高频面试问题与应答技巧6.1 可能被问到的扩展问题如果数组很大但内存有限怎么办答可以考虑外部排序双指针法分批加载数据如何修改代码使其返回所有可能的解答用列表存储所有满足条件的索引对如果数组已经排序如何优化答使用双指针法可以将空间复杂度降为O(1)6.2 白板编程时的注意事项先和面试官确认输入范围返回值要求异常处理方式写代码时边写边解释思路注意代码缩进和格式及时标注时间和空间复杂度测试时先过常规用例再检查边界条件最后验证性能6.3 如何展示你的优势从暴力解法开始展示思考过程逐步优化解释每一步的改进点讨论不同场景下的最优选择延伸到类似问题如三数之和7. 学习资源与进阶路线7.1 推荐学习资料书籍《算法导论》哈希表相关章节《编程珠玑》算法优化思想《剑指Offer》面试技巧在线课程LeetCode官方出品的算法课程Coursera上的Algorithmic Toolbox极客时间的算法面试通关课刷题平台LeetCode中文站牛客网真题练习Codeforces周赛7.2 同类题目训练清单简单难度两数之和两数之和 II - 输入有序数组两数之和 III - 数据结构设计中等难度三数之和四数之和四数相加 II困难难度最小区间黑名单中的随机数7.3 30天刷题计划示例阶段天数重点内容基础1-7哈希表相关题目强化8-14双指针技巧综合15-21多方法解题模拟22-28限时训练冲刺29-30错题复习8. 从题目到工程实践的思考在实际工程中两数之和的变体经常出现在这些场景电商系统中的凑单功能金融领域的风险对冲组合查找游戏中的装备合成系统一个典型的工程实现需要考虑class TwoSumService: def __init__(self): self.num_counts defaultdict(int) def add(self, number): self.num_counts[number] 1 def find(self, target): for num in self.num_counts: complement target - num if complement in self.num_counts: if complement ! num or self.num_counts[num] 1: return True return False这种实现支持高频添加操作实时查询大数据量处理9. 算法竞赛与面试刷题的区别很多同学容易混淆这两个场景的需求维度算法竞赛面试刷题目标快速解决新问题清晰解释经典问题代码风格追求极简强调可读性时间复杂度关注常数优化关注大O分析准备重点广泛涉猎深度掌握高频题评判标准通过测试用例整体表现对于两数之和这样的题目竞赛中可能要求处理1e6规模的数据面试中更关注代码的健壮性和沟通能力10. 个人经验与实用建议在带过上百名学员后我总结出这些经验不要死记硬背理解哈希表的思想比记住代码更重要建立解题模板把两数之和的解法抽象成可复用的模式善用可视化工具用绘图帮助理解指针移动和哈希映射记录错误案例把调试过程中的错误解法也保存下来模拟面试环境用白板或纯文本编辑器练习最后分享一个实用技巧当你在面试中遇到任何求和类问题时都可以先问自己这是两数之和的变体吗能用哈希表优化查找吗如果数组有序能否用双指针这种思维模式能帮你快速找到解题方向。记住刷题的目的不是背题而是培养解决问题的通用能力。两数之和就像算法世界的Hello World简单却蕴含着编程最本质的思考方式。
返回列表