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).
Auxiliary Space: O(1)
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.
Implementation:
// 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 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 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# 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 |
<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
// Find the number which is greater than // a[i] and power of two int cur = 1;
while (cur <= a[i])
cur <<= 1;
|
// Find the number which is greater than // a[i] and power of two int cur = 1;
while (cur <= a[i])
cur <<= 1;
|
// Find the number which is greater than // a[i] and power of two int cur = 1 ;
while (cur <= a[i])
cur <<= 1 ;
// This code is contributed by sourabhdalal0001 |
# Find the number which is greater # than a[i] and power of two cur = 1
while (cur < = a[i]):
cur = cur << 1
# This code is contributed by sourabhdalal0001
|
// Find the number which is greater than // a[i] and power of two int cur = 1;
while (cur <= a[i])
cur <<= 1;
// This code is contributed by utkarshshirode02. |
// 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)
Auxiliary Space: O(n)