Number of pairs whose sum is a power of 2
Given an array arr[] of positive integers, the task is to count the maximum possible number of pairs (arr[i], arr[j]) such that arr[i] + arr[j] is a power of 2.
Note: One element can be used at most once to form a pair.
Examples:
Input: arr[] = {3, 11, 14, 5, 13}
Output: 2
All valid pairs are (13, 3) and (11, 5) both sum up to 16 which is a power of 2.
We could have used (3, 5) but by doing so maximum of 1 pair could only be formed.
Therefore, (3, 5) is not optimal.
Input: arr[] = {1, 2, 3}
Output: 1
1 and 3 can be paired to form 4, which is a power of 2.
A simple solution is to consider every pair and check if sum of this pair is a power of 2 or not. Time Complexity of this solution is O(n * n)
An Efficient Approach: is to find the largest element from the array say X then find the largest element from the rest of the array elements Y such that Y ≤ X and X + Y is a power of 2. This is an optimal selection of pair because even if Y makes a valid pair with some other element say Z then Z will be left to pair with an element other than Y (if possible) to maximize the number of valid pairs.
C++
// C++ implementation of above approach #include <bits/stdc++.h> using namespace std; // Function to return the count of valid pairs int countPairs( int a[], int n) { // Storing occurrences of each element unordered_map< int , int > mp; for ( int i = 0; i < n; i++) mp[a[i]]++; // Sort the array in decreasing order sort(a, a + n, greater< int >()); // Start taking largest element each time int count = 0; for ( int i = 0; i < n; i++) { // If element has already been paired if (mp[a[i]] < 1) continue ; // Find the number which is greater than // a[i] and power of two int cur = 1; while (cur <= a[i]) cur <<= 1; // If there is a number which adds up with a[i] // to form a power of two if (mp[cur - a[i]]) { // Edge case when a[i] and crr - a[i] is same // and we have only one occurrence of a[i] then // it cannot be paired if (cur - a[i] == a[i] and mp[a[i]] == 1) continue ; count++; // Remove already paired elements mp[cur - a[i]]--; mp[a[i]]--; } } // Return the count return count; } // Driver code int main() { int a[] = { 3, 11, 14, 5, 13 }; int n = sizeof (a) / sizeof (a[0]); cout << countPairs(a, n); return 0; } |
Java
// Java implementation of above approach import java.util.TreeMap; class Count { // Function to return the count of valid pairs static int countPairs( int [] a, int n) { // To keep the element in sorted order TreeMap<Integer, Integer> map = new TreeMap<>(); for ( int i = 0 ; i < n; i++) { map.put(a[i], 1 ); } // Start taking largest element each time int count = 0 ; for ( int i = 0 ; i < n; i++) { // If element has already been paired if (map.get(a[i]) < 1 ) continue ; // Find the number which is greater than // a[i] and power of two int cur = 1 ; while (cur <= a[i]) cur <<= 1 ; // If there is a number which adds up with a[i] // to form a power of two if (map.containsKey(cur - a[i])) { // Edge case when a[i] and crr - a[i] is same // and we have only one occurrence of a[i] then // it cannot be paired if (cur - a[i] == a[i] && map.get(a[i]) == 1 ) continue ; count++; // Remove already paired elements map.put(cur - a[i], map.get(cur - a[i]) - 1 ); map.put(a[i], map.get(a[i]) - 1 ); } } // Return the count return count; } // Driver code public static void main(String[] args) { int [] a = { 3 , 11 , 14 , 5 , 13 }; int n = a.length; System.out.println(countPairs(a, n)); } } // This code is contributed by Vivekkumar Singh |
Python3
# Python3 implementation of above approach # Function to return the count # of valid pairs def countPairs(a, n) : # Storing occurrences of each element mp = dict .fromkeys(a, 0 ) for i in range (n) : mp[a[i]] + = 1 # Sort the array in decreasing order a.sort(reverse = True ) # Start taking largest element # each time count = 0 for i in range (n) : # If element has already been paired if (mp[a[i]] < 1 ) : continue # Find the number which is greater # than a[i] and power of two cur = 1 while (cur < = a[i]) : cur = cur << 1 # If there is a number which adds # up with a[i] to form a power of two if (cur - a[i] in mp.keys()) : # Edge case when a[i] and crr - a[i] # is same and we have only one occurrence # of a[i] then it cannot be paired if (cur - a[i] = = a[i] and mp[a[i]] = = 1 ) : continue count + = 1 # Remove already paired elements mp[cur - a[i]] - = 1 mp[a[i]] - = 1 # Return the count return count # Driver code if __name__ = = "__main__" : a = [ 3 , 11 , 14 , 5 , 13 ] n = len (a) print (countPairs(a, n)) # This code is contributed by Ryuga |
C#
// C# implementation of above approach using System; using System.Collections.Generic; class GFG { // Function to return the count of valid pairs static int countPairs( int [] a, int n) { // To keep the element in sorted order Dictionary< int , int > map = new Dictionary< int , int >(); for ( int i = 0; i < n; i++) { if (!map.ContainsKey(a[i])) map.Add(a[i], 1); } // Start taking largest element each time int count = 0; for ( int i = 0; i < n; i++) { // If element has already been paired if (map[a[i]] < 1) continue ; // Find the number which is greater than // a[i] and power of two int cur = 1; while (cur <= a[i]) cur <<= 1; // If there is a number which adds up // with a[i] to form a power of two if (map.ContainsKey(cur - a[i])) { // Edge case when a[i] and crr - a[i] // is same and we have only one occurrence // of a[i] then it cannot be paired if (cur - a[i] == a[i] && map[a[i]] == 1) continue ; count++; // Remove already paired elements map[cur - a[i]] = map[cur - a[i]] - 1; map[a[i]] = map[a[i]] - 1; } } // Return the count return count; } // Driver code public static void Main(String[] args) { int [] a = { 3, 11, 14, 5, 13 }; int n = a.Length; Console.WriteLine(countPairs(a, n)); } } // This code is contributed by Princi Singh |
Javascript
<script> // JavaScript Program to implement // the above approach // Function to return the count of valid pairs function countPairs(a, n) { // To keep the element in sorted order let map = new Map(); for (let i = 0; i < n; i++) { map.set(a[i], 1); } // Start taking largest element each time let count = 0; for (let i = 0; i < n; i++) { // If element has already been paired if (map.get(a[i]) < 1) continue ; // Find the number which is greater than // a[i] and power of two let cur = 1; while (cur <= a[i]) cur <<= 1; // If there is a number which adds up with a[i] // to form a power of two if (map.has(cur - a[i])) { // Edge case when a[i] and crr - a[i] is same // and we have only one occurrence of a[i] then // it cannot be paired if (cur - a[i] == a[i] && map.get(a[i]) == 1) continue ; count++; // Remove already paired elements map.set(cur - a[i], map.get(cur - a[i]) - 1); map.set(a[i], map.get(a[i]) - 1); } } // Return the count return count; } // Driver Code let a = [ 3, 11, 14, 5, 13 ]; let n = a.length; document.write(countPairs(a, n)); </script> |
2
Note that the below operation in above code can be done in O(1) time using the last approach discussed in Smallest power of 2 greater than or equal to n
C
// Find the number which is greater than // a[i] and power of two int cur = 1; while (cur <= a[i]) cur <<= 1; |
Javascript
// JavaScript program to find the // number which is greater than // a[i] and power of two var cur = 1; while (cur <= a[i]) cur <<= 1; //This code is contributed by phasing17 |
After optimizing above expression, time complexity of this solution becomes O(n Log n)