1. 求数组中两数相加和为K的所有组合
1.1 排序+指针
1. 先将数组排序 o(nlogn);
2. 再使用两个指针 o(n)。
1. 代码实现
def two_num_sum_k(arr, k):
if not arr or len(arr) < 2:
return []
result = []
arr.sort()
low, high = 0, len(arr) - 1
while low < high:
sum = arr[low] + arr[high]
if sum == k:
result.append((arr[low], arr[high]))
low += 1
high -= 1
elif sum < k:
low += 1
else:
high -= 1
return result
2. 测试
a = [-1, -2, 3, 4, 5, 6, 7]
k = 5
print(two_num_sum_k(a, k))
# [(-2, 7), (-1, 6)]
1.2 排序+二分查找
1. 先将数组排序 o(nlogn);
2. 再二分查找k-a[i]。 o(logn)*N
1.3 hash表
1. 先用hash表缓存 o(n);
2. 再在hash表中查找k-a[i]。 o(1)*N
2. 求数组中三数相加和为K的所有组合
3个数和为k <=> a+b=k-c 时间复杂度o(nlogn)
1. 代码实现
def three_num_sum_k(arr, k):
if not arr or len(arr) < 3:
return []
result = []
arr.sort()
for i in range(len(arr)-2):
low, high = i+1, len(arr) - 1
while low < high:
sum = arr[i] + arr[low] + arr[high]
if sum == k:
result.append((arr[i], arr[low], arr[high]))
low += 1
high -= 1
elif sum < k:
low += 1
else:
high -= 1
return result
2. 借助两数和为k
def three_num_sum_k2(arr, k):
result = []
if not arr or len(arr) < 3:
return result
arr.sort()
# 深拷贝一份,确保for循环时数组不变
a = arr.copy()
for x in arr:
a.remove(x)
temp = two_num_sum_k(a, k-x)
if temp:
for item in temp:
result.append((x, item[0], item[1]))
return result
3. 测试
a = [-1, -2, 3, 4, 5, 6, 7]
print(three_num_sum_k(a, k=8))
print(three_num_sum_k2(a, k=8))
# [(-2, 3, 7), (-2, 4, 6), (-1, 3, 6), (-1, 4, 5)]
3. 思路分析
数组A中N个数和为K的一组解
1. N-1个数中是否有和为K的解;
2. N-1个数中是否有和为K-A[N-1]的解;
DP动态规划方程:
P[N][K] = P[N-1][K] || P[N-1][K-A[N-1]]