class Solution {
public int threeSumMulti(int[] A, int target) {
// 计算每个数字出现的次数
// 计算三个数字为8的数字 三个数字 排序 三指针
// 每个数字选择 :C n k 几个里面选几个 (排列组合)
// 定义字典存储每个数字的出现个数
Map<Integer,Integer> number = new HashMap<Integer,Integer>();
for(int num:A){
// putIfAbsent()保存数据的时候,如果该链表中保存的有相同key的值,那么就不会对我们当前的value进行保存
number.putIfAbsent(num,0);
number.put(num,number.get(num)+1);
}
// 将字典的键值转为数组,并排序,方便遍历
int[] key = number.keySet().stream().mapToInt(integer -> integer).toArray();
Arrays.sort(key);
long ans = 0;
for(int i =0;i<key.length;i++){
int x = key[i];
int T = target-x;
// 由于可以重复,所以j从i开始
int j = i, k = key.length-1;
while(j<=k){
int y = key[j],z = key[k];
if(y+z<T){
j++;
}else if(y+z>T){
k--;
}else{
// 相等的情况
// 找到满足条件的三个数
if(i<j && j<k){
// C_n_1 = n
// C_n_2 = n*(n-1)/2*1
// C_n_3 = n*(n-1)*(n-2)/3*2*1
ans += (long)number.get(x)*(long)number.get(y)*(long)number.get(z);
}else if(i==j&&j<k){
ans += (long)number.get(x)*((long)number.get(x)-1) /2 * (long)number.get(z);
}else if(i<j && j == k){
ans += (long)number.get(x) * (long)number.get(y) * ((long)number.get(y) - 1) / 2;
}else{
// i == j == k
ans += (long)number.get(x) * ((long)number.get(x) - 1) * ((long)number.get(x) - 2) / 6;
}
ans %= 1000000007;
j++;
k--;
}
}
}
return (int)ans;
}
}
每日一道Leetcode - 923. 三数之和的多种可能【排序|三指针|排列组合】
猜你喜欢
转载自blog.csdn.net/weixin_41041275/article/details/111404477
今日推荐
周排行