Leetcode 923:三數之和的多種可能(最詳細的解法!!!)
阿新 • • 發佈:2018-11-12
給定一個整數陣列 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
中,這實際上是
。如果是第二種情況,我們將dict[i]*(dict[i] - 1)//2*dict[k]
加入到result
中,這實際上是
。如果是第三種情況,我們將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
如有問題,希望大家指出!!!