Skip to content
Related Articles

Related Articles

Improve Article

Number of pairs whose sum is a power of 2

  • Difficulty Level : Hard
  • Last Updated : 28 May, 2021

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:
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 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 deceasing 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 deceasing 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>
Output: 



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;

After optimizing above expression, time complexity of this solution becomes O(n Log n)
 

Want to learn from the best curated videos and practice problems, check out the C++ Foundation Course for Basic to Advanced C++ and C++ STL Course for the language and STL. To complete your preparation from learning a language to DS Algo and many more, please refer Complete Interview Preparation Course.



My Personal Notes arrow_drop_up
Recommended Articles
Page :