LeetCode #923 - 3Sum With Multiplicity

题目描述:

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

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

Example 1:

Input: A = [1,1,2,2,3,3,4,4,5,5], target = 8

Output: 20

Explanation: 

Enumerating by the values (A[i], A[j], A[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: A = [1,1,2,2,2,2], target = 5

Output: 12

Explanation: 

A[i] = 1, A[j] = A[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.

Note:

1. 3 <= A.length <= 3000

2. 0 <= A[i] <= 100

3. 0 <= target <= 300

class Solution {
public:
    int threeSumMulti(vector<int>& A, int target) {
        //需要计算多个hash[x]的乘积,如果每个hash[x]都是int类型,得到的乘积已经溢出,再赋值给long long类型的result还是错误的结果
        unordered_map<int,long long> hash;
        for(int num:A) hash[num]++;
        // 先统计每个数字的次数,然后按照不能重复的方法来计算
        sort(A.begin(),A.end());
        int n=A.size();
        long long result=0;
        for(int i=0;i<n-2;i++)
        {
            while(i>0&&A[i]==A[i-1]) i++;
            int j=i+1;
            int k=n-1;
            while(j<k)
            {
                if(A[i]+A[j]+A[k]==target) 
                {
                    if(A[i]!=A[j]&&A[j]!=A[k]) //全部不同
                        result+=hash[A[i]]*hash[A[j]]*hash[A[k]];
                    else if(A[i]==A[j]&&A[j]==A[k]) //全部相同
                        result+=hash[A[i]]*(hash[A[j]]-1)*(hash[A[k]]-2)/6;
                    else if(A[i]==A[j]&&A[j]!=A[k]) //A[i]==A[j]
                        result+=hash[A[i]]*(hash[A[j]]-1)/2*hash[A[k]];
                    else if(A[i]!=A[j]&&A[j]==A[k]) //A[j]==A[k]
                        result+=hash[A[i]]*hash[A[j]]*(hash[A[k]]-1)/2;
                    j++;
                    k--;
                    while(j<k&&A[j]==A[j-1]) j++;
                    while(k>j&&A[k]==A[k+1]) k--;
                }
                else if(A[i]+A[j]+A[k]<target) j++;
                else k--;
            }
        }
        long long mod=pow(10,9)+7;
        return result%mod;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值