题目:
A good meal is a meal that contains exactly two different food items with a sum of deliciousness equal to a power of two.
You can pick any two different foods to make a good meal.
Given an array of integers deliciousness
where deliciousness[i]
is the deliciousness of the ith
item of food, return the number of different good meals you can make from this list modulo 109 + 7
.
Note that items with different indices are considered different even if they have the same deliciousness value.
Example 1:
Input: deliciousness = [1,3,5,7,9] Output: 4 Explanation: The good meals are (1,3), (1,7), (3,5) and, (7,9). Their respective sums are 4, 8, 8, and 16, all of which are powers of 2.
Example 2:
Input: deliciousness = [1,1,1,3,3,3,7] Output: 15 Explanation: The good meals are (1,1) with 3 ways, (1,3) with 9 ways, and (1,7) with 3 ways.
Constraints:
1 <= deliciousness.length <= 10^5
0 <= deliciousness[i] <= 2^20
思路:
题目意思其实就是给定一个可能有重复数字的数组,找出数组中任意两数相加所得和为2的幂的所有组合,返回组合数量,并不要求具体组合,其中相同数字的不同个体视为不同。这里数量级在10的5次,因此二重循环遍历数组不可取。有个比较tricky的地方,数组中数字小于等于2的20次,隐含的意思就是任意两数之和必然小于等于2的21次,这也是解题关键。首先无可避免的是用哈希表来存数字和出现几次,然后我们先循环2的0次到2的21次,每一轮都有一个2的幂,作为我们的target和。第二重循环我们再遍历哈希表,找出能和当前数相加为target的数是否存在。这里因为同一个数比如两个1,相加是2也是成立的,因此如果是这个数本身的话,我们不用除以2,我们用ans1来记录;如果不是,我们先算在答案ans2中,这部分的总和是要除以2的,因为我们循环a时找了b,循环b时又找了一次a,因此最终返回的是ans1+ans2/2。另外就是注意mode,和一开始我们初始化ans1和ans2可以用long long来避免int无法承接数字。
代码:
class Solution {
public:
int countPairs(vector<int>& d) {
unordered_map<int,int> m;
int mod = 1e9+7;
for(auto i:d)
{
m[i]++;
}
long long ans1=0, ans2=0;
for(int i=0;i<=21;i++)
{
int target=pow(2,i);
for(auto itr=m.begin();itr!=m.end();itr++)
{
auto match=m.find(target-itr->first);
if(match==m.end())
continue;
if(match==itr)
{
long long t=itr->second;
ans1+=(t*(t-1))/2;
}
else
ans2+=match->second*itr->second;
}
ans1%=mod;
ans2%=mod;
}
return ans1+ans2/2;
}
};