Leetcode 923:三数之和的多种可能(最详细的解法!!!)

版权声明:本文为博主原创文章,未经博主允许不得转载。有事联系:[email protected] https://blog.csdn.net/qq_17550379/article/details/83088746

给定一个整数数组 A,以及一个整数 target 作为目标值,返回满足 i < j < kA[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 种情况。

提示:

  1. 3 <= A.length <= 3000
  2. 0 <= A[i] <= 100
  3. 0 <= target <= 300

解题思路

这个问题其实非常简单,我们对于a + b + c == target主要存在这样的三种情况。

  • a==b==c
  • a==b!=c
  • a<b and b<c

实际上这是一个组合问题,所以我没有考虑a,b,c的顺序,大家仔细思考一下。

所以我们参照这篇文章 k 数和问题的思路。我们通过一个dict记录A中的元素以及它们的个数。然后我们通过ij遍历dict。如果是第一种情况,我们将dict[i]*(dict[i] - 1)*(dict[i] - 2)//6加入到result中,这实际上是 C n 3 C_{n}^{3} 。如果是第二种情况,我们将dict[i]*(dict[i] - 1)//2*dict[k]加入到result中,这实际上是 C n 2 C_{n}^{2} 。如果是第三种情况,我们将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

如有问题,希望大家指出!!!

猜你喜欢

转载自blog.csdn.net/qq_17550379/article/details/83088746
今日推荐