Minimum number of given powers of 2 required to represent a number

Given an integer x and an array arr[] each element of which is a power of 2. The task is to find the minimum number of integer powers of 2 from the array which when added give x. If it is not possible to represent x with the given array elements then print -1.

Examples:

Input: arr[] = {2, 4, 8, 2, 4}, x = 14
Output: 3
14 can be written as 8 + 4 + 2

Input: arr[] = {2, 4, 8, 2, 4}, x = 5
Output: -1
5 cannot be represented as the sum any elements from the given array.



Approach: For each power of 2 let’s calculate the number of elements in the given array with the value equals this. Let’s call it cnt. It is obvious that we can obtain the value x greedily (because all fewer values of elements are divisors of all greater values of elements).

Now let’s iterate over all powers of 2 from 30 to 0. Let’s deg be the current degree. We can take min(x / 2deg, cntdeg) elements with the value equals 2deg. Let it be cur. Add cur to the answer and subtract 2deg * cur from x. Repeat the process until the x can no longer be reduced. If after iterating over all powers, x is still non-zero then print -1. Otherwise, print the answer.

Below is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
  
// Function to return the minimum number
// of given integer powers of 2 required
// to represent a number as sum of these powers
int power_of_two(int n, int a[], int x)
{
  
    // To store the count of powers of two
    vector<int> cnt(31);
  
    for (int i = 0; i < n; ++i) {
  
        // __builtin_ctz(a[i]) returns the count 
        // of trailing 0s in a[i]
        ++cnt[__builtin_ctz(a[i])];
    }
  
    int ans = 0;
    for (int i = 30; i >= 0 && x > 0; --i) {
  
        // If current power is available
        // in the array and can be used
        int need = min(x >> i, cnt[i]);
  
        // Update the answer
        ans += need;
  
        // Reduce the number
        x -= (1 << i) * need;
    }
  
    // If the original number is not reduced to 0
    // It cannot be represented as the sum
    // of the given powers of 2
    if (x > 0)
        ans = -1;
  
    return ans;
}
  
// Driver code
int main()
{
    int arr[] = { 2, 2, 4, 4, 8 }, x = 6;
    int n = sizeof(arr) / sizeof(arr[0]);
  
    cout << power_of_two(n, arr, x);
  
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java implementation of the approach 
import java.util.*;
  
class GFG
{
      
// __builtin_ctz(a[i]) returns the count 
// of trailing 0s in a[i] 
static int __builtin_ctz(int a)
{
    int count = 0;
    for(int i = 0; i < 40; i++)
    if(((a >> i) & 1) == 0)
    {
        count++;
    }
    else 
        break;
    return count;
}
  
// Function to return the minimum number 
// of given integer powers of 2 required 
// to represent a number as sum of these powers 
static int power_of_two(int n, int a[], int x) 
  
    // To store the count of powers of two 
    Vector<Integer> cnt = new Vector<Integer>(); 
      
    for (int i = 0; i < 31; ++i)
        cnt.add(0);
  
    for (int i = 0; i < n; ++i) 
    
  
        // __builtin_ctz(a[i]) returns the count 
        // of trailing 0s in a[i] 
          
        cnt.set(__builtin_ctz(a[i]), 
        (cnt.get(__builtin_ctz(a[i]))==null) ?
        1 : cnt.get(__builtin_ctz(a[i]))+1); 
    
  
    int ans = 0
    for (int i = 30; i >= 0 && x > 0; --i) 
    
  
        // If current power is available 
        // in the array and can be used 
        int need = Math.min(x >> i, cnt.get(i)); 
  
        // Update the answer 
        ans += need; 
  
        // Reduce the number 
        x -= (1 << i) * need; 
    
  
    // If the original number is not reduced to 0 
    // It cannot be represented as the sum 
    // of the given powers of 2 
    if (x > 0
        ans = -1
  
    return ans; 
  
// Driver code 
public static void main(String args[])
    int arr[] = { 2, 2, 4, 4, 8 }, x = 6
    int n = arr.length; 
    System.out.println(power_of_two(n, arr, x)); 
}
  
// This code is contributed by Arnab Kundu

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# implementation of the approach 
using System;
  
class GFG
{
      
// __builtin_ctz(a[i]) returns the count 
// of trailing 0s in a[i] 
static int __builtin_ctz(int a)
{
    int count = 0;
    for(int i = 0; i < 40; i++)
    if(((a >> i) & 1) == 0)
    {
        count++;
    }
    else
        break;
    return count;
}
  
// Function to return the minimum number 
// of given integer powers of 2 required 
// to represent a number as sum of these powers 
static int power_of_two(int n, int []a, int x) 
  
    // To store the count of powers of two 
    int[] cnt = new int[32]; 
  
    for (int i = 0; i < n; ++i) 
    
  
        // __builtin_ctz(a[i]) returns the count 
        // of trailing 0s in a[i] 
          
        cnt[__builtin_ctz(a[i])] = 
        cnt[__builtin_ctz(a[i])] == 
        0?1 : cnt[__builtin_ctz(a[i])] + 1; 
    
  
    int ans = 0; 
    for (int i = 30; i >= 0 && x > 0; --i) 
    
  
        // If current power is available 
        // in the array and can be used 
        int need = Math.Min(x >> i, cnt[i]); 
  
        // Update the answer 
        ans += need; 
  
        // Reduce the number 
        x -= (1 << i) * need; 
    
  
    // If the original number is not reduced to 0 
    // It cannot be represented as the sum 
    // of the given powers of 2 
    if (x > 0) 
        ans = -1; 
  
    return ans; 
  
// Driver code 
static void Main()
    int []arr = { 2, 2, 4, 4, 8 };
    int x = 6; 
    int n = arr.Length; 
    Console.WriteLine(power_of_two(n, arr, x)); 
}
  
// This code is contributed by mits

chevron_right


Output:

2


My Personal Notes arrow_drop_up

pawanasipugmailcom

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.



Improved By : andrew1234, Mithun Kumar