1711. Count Good Meals
Description
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 <= 1050 <= deliciousness[i] <= 220
Solutions
Solution 1: Hash Table + Enumeration of Powers of Two
Thinking
Counting unordered pairs whose sum is a power of two by enumerating all index pairs is \(O(n^2)\) and fails for \(n\le 10^5\).
Values are at most \(2^{20}\), so only \(O(\log M)\) candidate powers exist. For each seen \(d\), enumerate a power \(s\) and look up \(s-d\) in a hash map.
Insert \(d\) into the counter after querying so each pair is counted once against earlier elements. Reduce the answer modulo \(10^9+7\).
According to the problem, we need to count the number of combinations in the array where the sum of two numbers is a power of \(2\). Directly enumerating all combinations has a time complexity of \(O(n^2)\), which will definitely time out.
We can traverse the array and use a hash table \(cnt\) to maintain the number of occurrences of each element \(d\) in the array.
For each element, we enumerate the powers of two \(s\) as the sum of two numbers from small to large, and add the number of occurrences of \(s - d\) in the hash table to the answer. Then increase the number of occurrences of the current element \(d\) by one.
After the traversal ends, return the answer.
The time complexity is \(O(n \times \log M)\), where \(n\) is the length of the array deliciousness, and \(M\) is the upper limit of the elements. For this problem, the upper limit \(M=2^{20}\).
We can also use a hash table \(cnt\) to count the number of occurrences of each element in the array first.
Then enumerate the powers of two \(s\) as the sum of two numbers from small to large. For each \(s\), traverse each key-value pair \((a, m)\) in the hash table. If \(s - a\) is also in the hash table, and \(s - a \neq a\), then add \(m \times cnt[s - a]\) to the answer; if \(s - a = a\), then add \(m \times (m - 1)\) to the answer.
Finally, divide the answer by \(2\), modulo \(10^9 + 7\), and return.
The time complexity is the same as the method above.
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
1 2 3 4 5 6 7 8 9 10 11 12 | |
Solution 2
Thinking
Solution 1 queries while scanning. We may instead count all frequencies first, then enumerate each power \(s\) and each key \(a\), pairing with \(cnt[s-a]\).
Use \(m(m-1)\) when \(a=s-a\) and \(m\cdot cnt[s-a]\) otherwise. Each pair is counted twice, so shift right once before taking modulo. The complexity remains \(O(n\log M)\).
1 2 3 4 5 6 7 8 9 10 11 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | |