leetcode_923 三数之和的多种可能

95 阅读1分钟

要求

给定一个整数数组 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] = 1A[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

核心代码

class Solution:
    def threeSumMulti(self, arr: List[int], target: int) -> int:
        from collections import Counter
        c = Counter(arr)
        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)

image.png

解题思路:这个其实是一道排列组合问题,我们首先先对我们的数据进行统计个数,分成三种情况,第一种情况我们的三个数字都是一样的时候,我们其实是从n个数字中选择三个,Cn3 = x * (x - 1) * (x - 2) //6,第二种就是两个数字相同,我们其实是从n个数字中选择三个,Cn2 * 不同的数的个数 = x * (x - 1) // 2 * c[k],第三种就是数字都不相同,我们其实是,就是从各自的个数中分别取出一个就行 = x * y * c[k],所以就是排列组合。