题目
给定四个包含整数的数组列表 A , B , C , D
,计算有多少个元组 (i, j, k, l)
,使得 A[i] + B[j] + C[k] + D[l] = 0
。
为了使问题简单化,所有的 A, B, C, D
具有相同的长度 N
,且 0 ≤ N ≤ 500
。所有整数的范围在 到
之间,最终结果不会超过
。
例如:
输入:
A = [ 1, 2]
B = [-2,-1]
C = [-1, 2]
D = [ 0, 2]
输出:
2
解释:
两个元组如下:
1. (0, 0, 0, 1) -> A[0] + B[0] + C[0] + D[1] = 1 + (-2) + (-1) + 2 = 0
2. (1, 1, 0, 0) -> A[1] + B[1] + C[0] + D[0] = 2 + (-1) + (-1) + 0 = 0
方案一(穷举法)
func fourSumCount(A []int, B []int, C []int, D []int) int {
N := len(A)
count := 0
for i := 0; i < N; i++ {
for j := 0; j < N; j++ {
for a := 0; a < N; a++ {
for b := 0; b < N; b++ {
if A[i] + B[j] + C[a] + D[b] == 0 {
count += 1
}
}
}
}
}
return count
}
- 时间复杂度
- leetcode 超时
方案二
func fourSumCount(A []int, B []int, C []int, D []int) int {
// 只需 (A[a] + B[b] + C[c]) in m4 即可
m4 := map[int]int{}
for _, d := range D {
m4[-d] += 1
}
// 利用m4 和 C[] 构建 m3
// 只需 (A[a] + B[b]) in m3 即可
m3 := map[int]int{}
for _, c := range C {
for k, v := range m4 {
m3[k - c] += v
}
}
// 同理构建 m2
m2 := map[int]int{}
for _, b := range B {
for k, v := range m3 {
m2[k - b] += v
}
}
// 构建 m1
m1 := map[int]int{}
for _, a := range A {
for k, v := range m2 {
m1[k - a] += v
}
}
return m1[0]
}
- 时间复杂度
- leetcode 仍旧超时
代码可以优化的地方有很多,主要思想是
- A[a] + B[b] == val, 可能有多种 a, b 的组合,但是后续计算时候只需要计算
val
即可,不需要每一个组合都算出来 - 倒着计算使得更容易缓存结果
方案三(A + B = -(C + D))
func fourSumCount(A []int, B []int, C []int, D []int) int {
// A + B = -(C + D)
m1 := map[int]int{}
for _, a := range A {
for _, b := range B {
m1[a + b] += 1
}
}
count := 0
for _, c := range C {
for _, d := range D {
if v, ok := m1[-(c + d)]; ok {
count += v
}
}
}
return count
}
- 时间复杂度
原文
https://leetcode-cn.com/explore/learn/card/hash-table/207/conclusion/828/