Given an integer array, return the number of pairs of indices such that its array values sum to a power of 2. For reference, powers of 2 are: 2^0 = 1, 2^1 = 2, 2^2 = 4, 2^3 = 8, 2^4 = 16, etc...
Example:
a = [1, -1, 2, 3]
Output: 5
(0,0) = 1 + 1 = 2 (which is a power of 2)
(1,2) = -1 + 2 = 1 (which is a power of 2)
(1,3) = -1 + 3 = 2 (which is a power of 2)
(0,3) = 1 + 3 = 4 (which is a power of 2)
(2,2) = 2 + 2 = 4 (which is a power of 2)
Therefore, there are 5 pairs of indices whose array values sum is a power of 2 so the output is 5.
As implied by the above example, indices can be re-used.
My approach was a dynamic programming solution. However, I wasn't completely successful at passing all the test cases so I'm wondering if someone can give me some pointers as to where I went wrong and suggest another way of thinking about it.
Define recurrence:
Let F(i) = the number of pairs of indices that sum to a power of 2 ending at array index i.
Using the above example, F(0) = 1 because (0,0) = 1 + 1 = 2 which is a power of 2.
F(1) = 1 because with the addition of -1, there is still only one valid pair of indices.
F(2) = 3 because with the addition of 2, (2,2) and (1,2) are now valid indices along with (0,0).
F(3) = 5 following the same logic.
So the recurrence is something like:
F(i) = F(i-1) + number of sums to power of 2 for indices (0, i), (1, i), (2, i), ...., (i-1, i), (i, i).
My bottom-up dynamic programming solutin is below. It passed about 70% of the test cases so I am wondering if anyone can help guide me as to what I did wrong. Thanks.
boolean numPairsSumPowerOfTwo(int[] numbers) {
int[] dp = new int[numbers.length];
// Initialize base case
if (isPowerOfTwo(numbers[0]))
dp[0] = 1;
else
dp[0] = 0;
for (int i = 1; i < numbers.length; i++) {
int numNewSumsToPowerOfTwo = 0;
for (int j = 0; j <= i; j++) {
if (isPowerOfTwo(numbers[i] + numbers[j]))
numNewSumsToPowerOfTwo++;
}
dp[i] = numNewSumsToPowerOfTwo;
}
return dp[dp.length - 1];
}
boolean isPowerOfTwo(int n) {
if (n <= 0) return false;
if (n == 1) return true;
while (n > 1) {
if (n % 2 == 1)
return false;
n /= 2;
}
return true;
}