LeetCode #923 3Sum With Multiplicity 三數之和的多種可能 923 3Sum With Multiplicity 三數之和的多種可能

923 3Sum With Multiplicity 三數之和的多種可能

Description:
Given an integer array arr, and an integer target, return the number of tuples i, j, k such that i < j < k and arr[i] + arr[j] + arr[k] == target.

As the answer can be very large, return it modulo 10^9 + 7.

Example:

Example 1:

Input: arr = [1,1,2,2,3,3,4,4,5,5], target = 8
Output: 20
Explanation:
Enumerating by the values (arr[i], arr[j], arr[k]):
(1, 2, 5) occurs 8 times;
(1, 3, 4) occurs 8 times;
(2, 2, 4) occurs 2 times;
(2, 3, 3) occurs 2 times.

Example 2:

Input: arr = [1,1,2,2,2,2], target = 5
Output: 12
Explanation:
arr[i] = 1, arr[j] = arr[k] = 2 occurs 12 times:
We choose one 1 from [1,1] in 2 ways,
and two 2s from [2,2,2,2] in 6 ways.

Constraints:

3 <= arr.length <= 3000
0 <= arr[i] <= 100
0 <= target <= 300

題目描述:
給定一個整數數組 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

思路:

雙指針
用兩個指針分別查詢兩數之和等於 target - element[i] 的元素個數
如果 l == r == i, 三個數字相同結果數爲 C(m, 3), 其中 m 爲數字的個數
如果 l == r, 或者 l == i, 兩個數字相同結果數爲 C(p, 2) * q, p 爲相同的數字的個數, q 爲剩下的那個數字的個數
否則結果數爲 abc, a, b, c 分別爲三個數字的個數
時間複雜度爲 O(n + m ^ 2), 空間複雜度爲 O(m), arr 中最大的數字爲 m, 此題爲 100, 時間複雜度可看作 O(n)

代碼:
C++:

class Solution 
{
public:
    int threeSumMulti(vector<int>& arr, int target) 
    {
        long result = 0, mod = 1e9 + 7;
        vector<long> count(101, 0), element;
        for (const auto& num : arr) ++count[num];
        for (int i = 0; i < 101; i++) if (count[i]) element.emplace_back(i);
        for (int i = 0, n = element.size(); i < n; i++)
        {
            if (target < 3 * element[i]) break;
            int remain = target - element[i], l = i, r = n - 1;
            while (l <= r) 
            {
                if (element[l] + element[r] > remain) --r;
                else if (element[l] + element[r] < remain) ++l;
                else
                {
                    if (l == r and l == i) result += (count[element[i]] - 2) * (count[element[i]] - 1) * count[element[i]] / 6;
                    else if (l == i) result += (count[element[r]] * ((count[element[i]] - 1) * count[element[i]])) >> 1;
                    else if (l == r) result += (((count[element[l]] - 1) * count[element[l]]) >> 1) * count[element[i]];
                    else result += count[element[l]] * count[element[r]] * count[element[i]];
                    ++l;
                    --r;
                }
            }
        }
        return result % mod;
    }
};

Java:

class Solution {
    public int threeSumMulti(int[] arr, int target) {
        long result = 0, mod = 1_000_000_007, count[] = new long[101];
        for (int num : arr) ++count[num];
        List<Integer> element = new ArrayList<>();
        for (int i = 0; i < 101; i++) if (count[i] != 0) element.add(i);
        for (int i = 0, n = element.size(); i < n; i++) {
            if (target < 3 * element.get(i)) break;
            int remain = target - element.get(i), l = i, r = n - 1;
            while (l <= r) {
                if (element.get(l) + element.get(r) > remain) --r;
                else if (element.get(l) + element.get(r) < remain) ++l;
                else {
                    if (l == r && l == i) result += (count[element.get(i)] - 2) * (count[element.get(i)] - 1) * count[element.get(i)] / 6;
                    else if (l == i) result += (count[element.get(r)] * ((count[element.get(i)] - 1) * count[element.get(i)])) >>> 1;
                    else if (l == r) result += (((count[element.get(r)] - 1) * count[element.get(r)]) >>> 1) * count[element.get(i)];
                    else result += count[element.get(l)] * count[element.get(r)] * count[element.get(i)];
                    ++l;
                    --r;
                }
            }
        }
        return (int)(result % mod);
    }
}

Python:

class Solution:
    def threeSumMulti(self, arr: List[int], target: int) -> int:
        result, n, mod = 0, len(element := sorted((c := Counter(arr)).keys())), 10 ** 9 + 7
        for i in range(n):
            if target < 3 * element[i]: 
                break
            remain, l, r = target - element[i], i, n - 1
            while l <= r:
                if element[l] + element[r] > remain: 
                    r -= 1
                elif element[l] + element[r] < remain: 
                    l += 1
                else:
                    if l == r == i:
                        result += (c[element[i]] - 2) * (c[element[i]] - 1) * c[element[i]] // 6
                    elif l == i:
                        result += (c[element[r]] * ((c[element[i]] - 1) * c[element[i]])) >> 1
                    elif l == r:
                        result += (((c[element[l]] - 1) * c[element[l]]) >> 1) * c[element[i]]
                    else:
                        result += c[element[l]] * c[element[r]] * c[element[i]]
                    l, r = l + 1, r - 1
        return result % mod
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章