LeetCode 170. 两数之和 III - 数据结构设计
题目描述
思路分析
解法一:哈希表(推荐)
核心思路:
- 使用
HashMap记录每个数字出现的次数(支持重复数字)add(number)操作直接将数字加入哈希表,计数 +1find(value)操作枚举哈希表中每个 key,判断value - key是否存在- 对于
value - key == key的情况,需要该数字出现次数 >= 2- 空间换时间,
add为 O(1),find为 O(n)
复杂度分析:
- 时间复杂度:add O(1),find O(n),其中 n 为已添加的数字个数
- 空间复杂度:O(n),哈希表存储所有已添加的数字
class TwoSum {
private Map<Integer, Integer> countMap;
public TwoSum() {
countMap = new HashMap<>();
}
public void add(int number) {
// 记录每个数字出现次数
countMap.put(number, countMap.getOrDefault(number, 0) + 1);
}
public boolean find(int value) {
for (Map.Entry<Integer, Integer> entry : countMap.entrySet()) {
int num = entry.getKey();
int complement = value - num;
if (complement == num) {
// 两个相同的数,需要出现至少两次
if (entry.getValue() >= 2) {
return true;
}
} else {
// 两个不同的数,complement 存在即可
if (countMap.containsKey(complement)) {
return true;
}
}
}
return false;
}
}
type TwoSum struct {
countMap map[int]int
}
func Constructor() TwoSum {
return TwoSum{countMap: make(map[int]int)}
}
func (t *TwoSum) Add(number int) {
// 记录每个数字出现次数
t.countMap[number]++
}
func (t *TwoSum) Find(value int) bool {
for num, cnt := range t.countMap {
complement := value - num
if complement == num {
// 两个相同的数,需要出现至少两次
if cnt >= 2 {
return true
}
} else {
// 两个不同的数,complement 存在即可
if _, ok := t.countMap[complement]; ok {
return true
}
}
}
return false
}
解法二:有序列表 + 双指针
核心思路:
- 用
List存储所有数字,add时将数字加入列表find时先对列表排序,再用双指针从两端向中间逼近- 适合
add频率低、find频率高的场景- 若
add多find少,则每次find排序代价较高
复杂度分析:
- 时间复杂度:add O(1),find O(n log n),其中 n 为已添加的数字个数
- 空间复杂度:O(n),列表存储所有数字
class TwoSum {
private List<Integer> nums;
public TwoSum() {
nums = new ArrayList<>();
}
public void add(int number) {
nums.add(number);
}
public boolean find(int value) {
Collections.sort(nums);
int left = 0;
int right = nums.size() - 1;
while (left < right) {
int sum = nums.get(left) + nums.get(right);
if (sum == value) {
return true;
} else if (sum < value) {
left++;
} else {
right--;
}
}
return false;
}
}
import "sort"
type TwoSum struct {
nums []int
}
func Constructor() TwoSum {
return TwoSum{}
}
func (t *TwoSum) Add(number int) {
t.nums = append(t.nums, number)
}
func (t *TwoSum) Find(value int) bool {
sorted := make([]int, len(t.nums))
copy(sorted, t.nums)
sort.Ints(sorted)
left, right := 0, len(sorted)-1
for left < right {
sum := sorted[left] + sorted[right]
if sum == value {
return true
} else if sum < value {
left++
} else {
right--
}
}
return false
}
相似题目
| 题目 | 难度 | 考察点 |
|---|---|---|
| 1. 两数之和 | 简单 | 哈希表 |
| 167. 两数之和 II - 输入有序数组 | 中等 | 双指针 |
| 653. 两数之和 IV - 输入二叉搜索树 | 简单 | 哈希表、二叉树 |
| 15. 三数之和 | 中等 | 双指针、排序 |
| 18. 四数之和 | 中等 | 双指针、排序 |
| 560. 和为 K 的子数组 | 中等 | 哈希表、前缀和 |
本博客所有文章除特别声明外,均采用
CC BY-NC-SA 4.0
许可协议,转载请注明出处!