难度:中等。
标签:数组,哈希表。
使用字典存储美味值以及该值出现的个数。
将不重复的美味值放在list中并排序。
由于美味值的最大值为
2
20
2^{20}
220,因此两个食物的美味值之和最大为
2
21
2^{21}
221,将小于
2
22
2^{22}
222的幂计算出来存于mi数组中。
遍历list,list[i]与比其小的食物组合美味值取值范围位
[
l
i
s
t
[
i
]
,
l
i
s
t
[
i
]
∗
2
]
[list[i], list[i] * 2]
[list[i],list[i]∗2],因此找到该范围内的幂,减去list[i],得到x,根据x的出现次数更新组合个数。
正确解法:
class Solution {
vector<int> getMi(){
vector<int> arr(1, 1);
int a = 1;
for(int i = 1; i <= 22; ++i){
a = a * 2;
arr.emplace_back(a);
}
return arr;
}
int getNum(int a, int max){
int ans = 0;
for(int i = 1; i < a; ++i){
ans += i;
ans %= max;
}
return ans;
}
public:
int countPairs(vector<int>& deliciousness) {
int ans = 0;
int max = pow(10, 9) + 7;
vector<int> mi = getMi();
unordered_map<int, int> maps;
for(int i = 0; i < deliciousness.size(); ++i){
maps[deliciousness[i]]++;
}
vector<int> list;
for(auto it = maps.begin(); it != maps.end(); ++it){
list.emplace_back((*it).first);
}
sort(list.begin(), list.end());
/*cout << "list: ";
for(int i = 0; i < list.size(); ++i)cout << list[i] << " ";
cout << endl << endl;
cout << "mi: ";
for(int i = 0; i < mi.size(); ++i)cout << i << " " << mi[i] << endl;
cout << endl << endl;*/
for(int i = list.size() - 1; i >= 0; --i){
int left = -1, right = -1;
for(int k = 0; k < mi.size(); ++k){
if(left == -1 && mi[k] >= list[i])left = k;
if(right == -1 && mi[k] > list[i] * 2){
right = k - 1;
break;
}
}
// cout << list[i] << " " << left << " " << right << endl;
for(int k = left; k <= right; ++k){
int other = mi[k] - list[i];
if(other == list[i]){
ans += getNum(maps[list[i]], max);
ans %= max;
}
else if(maps[other] > 0){
ans += maps[list[i]] * maps[other];
ans %= max;
}
}
}
return ans;
}
};
结果: