文章目录
- 1. 问题背景
- 2. 两数之和(Two Sum)
- 2.1 问题描述
- 2.2 哈希表解法
- 代码实现
- 关键点解析
- 复杂度对比
- 3. 三数之和(3Sum)
- 3.1 问题描述
- 3.2 排序+双指针解法
- 代码实现
- 关键点解析
- 复杂度分析
- 4. 对比总结
- 5. 常见问题解答
- 6. 扩展练习
1. 问题背景
在算法面试和编程练习中,**两数之和(Two Sum)和三数之和(3Sum)**是两个经典的数组处理问题。这两个问题不仅是检验基础算法能力的试金石,也是理解高效搜索技巧的重要案例。本文将通过Java代码实现这两个问题,并深入解析其优化思路。
2. 两数之和(Two Sum)
2.1 问题描述
1. 两数之和
2.2 哈希表解法
代码实现
import java.util.HashMap;
import java.util.Map;public class TwoSum {public int[] twoSum(int[] nums, int target) {Map<Integer, Integer> numMap = new HashMap<>();for (int i = 0; i < nums.length; i++) {int complement = target - nums[i];if (numMap.containsKey(complement)) {return new int[] { numMap.get(complement), i };}numMap.put(nums[i], i);}return new int[0];}
}
关键点解析
特性 | 说明 |
---|---|
时间复杂度O(n) | 哈希表使查找时间降为O(1),只需一次遍历 |
空间复杂度O(n) | 最坏情况需存储所有元素 |
防重复机制 | 先检查补数再存入当前元素,避免自重复(如target=6, nums=[3,3] 场景) |
键值设计 | 键为数组值,值为索引,便于快速查找 |
复杂度对比
方法 | 时间复杂度 | 空间复杂度 | 适用场景 |
---|---|---|---|
暴力枚举 | O(n²) | O(1) | 小规模数据 |
哈希表 | O(n) | O(n) | 通用最优解 |
3. 三数之和(3Sum)
3.1 问题描述
15. 三数之和
3.2 排序+双指针解法
代码实现
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;public class ThreeSum {public List<List<Integer>> threeSum(int[] nums) {List<List<Integer>> result = new ArrayList<>();if (nums == null || nums.length < 3) return result;Arrays.sort(nums); // 关键预处理for (int i = 0; i < nums.length - 2; i++) {if (i > 0 && nums[i] == nums[i-1]) continue; // 跳过重复起点if (nums[i] > 0) break; // 提前终止int left = i + 1, right = nums.length - 1;while (left < right) {int sum = nums[i] + nums[left] + nums[right];if (sum == 0) {result.add(Arrays.asList(nums[i], nums[left], nums[right]));while (left < right && nums[left] == nums[left+1]) left++; // 跳过左重复while (left < right && nums[right] == nums[right-1]) right--; // 跳过右重复left++;right--;} else if (sum < 0) {left++; // 需要更大的数} else {right--; // 需要更小的数}}}return result;}
}
关键点解析
策略 | 作用 |
---|---|
排序预处理 | 使双指针法成为可能,同时便于去重 |
外层循环去重 | if (i>0 && nums[i]==nums[i-1]) 避免重复的基准元素 |
双指针收缩 | 当sum=0 时同时移动左右指针,避免遗漏解 |
内层循环去重 | 在找到有效解后,跳过所有与当前左右指针相同的元素 |
提前终止条件 | 当基准元素nums[i]>0 时,后续不可能出现有效解 |
复杂度分析
操作 | 时间复杂度 | 说明 |
---|---|---|
排序 | O(n log n) | 快速排序基础复杂度 |
双指针遍历 | O(n²) | 外层循环O(n),内层双指针O(n) |
总复杂度 | O(n²) | 主导项为双指针遍历 |
4. 对比总结
维度 | 两数之和 | 三数之和 |
---|---|---|
核心思想 | 哈希表快速查找 | 排序+双指针+去重 |
时间复杂度 | O(n) | O(n²) |
空间复杂度 | O(n) | O(1)(不计结果存储) |
难点 | 避免元素自重复 | 多维度去重与指针协同移动 |
扩展性 | 可扩展至Two Sum II(有序数组) | 可扩展至4Sum、KSum问题 |
5. 常见问题解答
Q1:为什么三数之和需要先排序?
排序后可以使用双指针法将时间复杂度从O(n³)优化到O(n²),同时便于跳过重复元素。
Q2:如何处理输入数组中的重复元素?
- 外层循环跳过相同基准元素
- 找到有效解后,内层循环跳过相同左右指针值
Q3:哈希表法为什么不适合三数之和?
虽然理论上可以使用哈希表存储两数之和,但难以高效处理去重问题,且空间复杂度会显著增加。
6. 扩展练习
- 四数之和(4Sum):尝试将三数之和的解法扩展到四数之和
- 最接近的三数之和:寻找与目标值最接近的三数组合
- 两数之和变种:设计支持频繁查询的数据结构
通过掌握这两个经典问题的解法,可以深入理解哈希表与双指针法的应用场景,并为解决更复杂的KSum问题打下坚实基础。