给定一个整数数组 A
,以及一个整数 target
作为目标值,返回满足 i < j < k
且 A[i] + A[j] + A[k] == target
的元组 i, j, k
的数量。
由于结果会非常大,请返回 结果除以 10^9 + 7 的余数
。
示例 1:
输入:A = [1,1,2,2,3,3,4,4,5,5], target = 8
输出:20
解释:
按值枚举(A[i],A[j],A[k]):
(1, 2, 5) 出现 8 次;
(1, 3, 4) 出现 8 次;
(2, 2, 4) 出现 2 次;
(2, 3, 3) 出现 2 次。
示例 2:
输入:A = [1,1,2,2,2,2], target = 5
输出:12
解释:
A[i] = 1,A[j] = A[k] = 2 出现 12 次:
我们从 [1,1] 中选择一个 1,有 2 种情况,
从 [2,2,2,2] 中选出两个 2,有 6 种情况。
提示:
3 <= A.length <= 3000
0 <= A[i] <= 100
0 <= target <= 300
解题思路
这个问题其实非常简单,我们对于a + b + c == target
主要存在这样的三种情况。
a==b==c
a==b!=c
a<b and b<c
实际上这是一个组合问题,所以我没有考虑a,b,c
的顺序,大家仔细思考一下。
所以我们参照这篇文章 k 数和问题的思路。我们通过一个dict
记录A
中的元素以及它们的个数。然后我们通过i
和j
遍历dict
。如果是第一种情况,我们将dict[i]*(dict[i] - 1)*(dict[i] - 2)//6
加入到result
中,这实际上是
C
n
3
C_{n}^{3}
Cn3。如果是第二种情况,我们将dict[i]*(dict[i] - 1)//2*dict[k]
加入到result
中,这实际上是
C
n
2
C_{n}^{2}
Cn2。如果是第三种情况,我们将dict[i]*dict[j]*dict[k]
加入到result
中。
from collections import Counter
class Solution:
def threeSumMulti(self, A, target):
"""
:type A: List[int]
:type target: int
:rtype: int
"""
c = Counter(A)
result = 0
for i, x in c.items():
for j, y in c.items():
k = target - i - j
if k not in c:
continue
if i == j == k:
result += x * (x - 1) * (x - 2) // 6
elif i == j != k:
result += x * (x - 1) // 2 * c[k]
elif i < j and j < k:
result += x * y * c[k]
return result % (10**9 + 7)
这是我认为思路最清晰的答案,对于其他的答案大家其实可以不用去看了,因为很容易将你拉入排列组合的泥潭中。
我将该问题的其他语言版本添加到了我的GitHub Leetcode
如有问题,希望大家指出!!!