Minimum number of given powers of 2 required to represent a number
Last Updated :
03 Oct, 2023
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++
#include <bits/stdc++.h>
using namespace std;
int power_of_two( int n, int a[], int x)
{
vector< int > cnt(31);
for ( int i = 0; i < n; ++i) {
++cnt[__builtin_ctz(a[i])];
}
int ans = 0;
for ( int i = 30; i >= 0 && x > 0; --i) {
int need = min(x >> i, cnt[i]);
ans += need;
x -= (1 << i) * need;
}
if (x > 0)
ans = -1;
return ans;
}
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;
}
|
Java
import java.util.*;
class GFG
{
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;
}
static int power_of_two( int n, int a[], int x)
{
Vector<Integer> cnt = new Vector<Integer>();
for ( int i = 0 ; i < 31 ; ++i)
cnt.add( 0 );
for ( int i = 0 ; i < n; ++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)
{
int need = Math.min(x >> i, cnt.get(i));
ans += need;
x -= ( 1 << i) * need;
}
if (x > 0 )
ans = - 1 ;
return ans;
}
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));
}
}
|
python
def power_of_two( n, a, x):
cnt = [ 0 for i in range ( 31 )]
for i in range (n):
count = 0
xx = a[i]
while ((xx & 1 ) = = 0 ):
xx = xx >> 1
count + = 1
cnt[count] + = 1
ans = 0
for i in range ( 30 , - 1 , - 1 ):
if x< = 0 :
continue
need = min (x >> i, cnt[i])
ans + = need
x - = ( 1 << i) * need
if (x > 0 ):
ans = - 1
return ans
arr = [ 2 , 2 , 4 , 4 , 8 ]
x = 6
n = len (arr)
print (power_of_two(n, arr, x))
|
C#
using System;
class GFG
{
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;
}
static int power_of_two( int n, int []a, int x)
{
int [] cnt = new int [32];
for ( int i = 0; i < n; ++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)
{
int need = Math.Min(x >> i, cnt[i]);
ans += need;
x -= (1 << i) * need;
}
if (x > 0)
ans = -1;
return ans;
}
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));
}
}
|
Javascript
<script>
function power_of_two( n, a, x)
{
let cnt = [];
for (let i = 0;i<31;i++)
cnt.push(0);
for (let i = 0; i < n; ++i) {
let count = 0;
let xx = a[i];
while ((xx & 1) == 0){
xx = xx >> 1
count += 1
}
cnt[count]+=1;
}
let ans = 0;
for (let i = 30; i >= 0 && x > 0; --i) {
let need = Math.min(x >> i, cnt[i]);
ans += need;
x -= (1 << i) * need;
}
if (x > 0)
ans = -1;
return ans;
}
let arr = [ 2, 2, 4, 4, 8 ], x = 6;
let n = arr.length;
document.write( power_of_two(n, arr, x));
</script>
|
Time Complexity: O(N)
Auxiliary Space: O(32), since no extra space has been taken.
Another Approach(Space optimization):
We can Binary search to find the index such that a[index] <= x .and reduce x to x-a[index] and increase ans by 1. and until our x become 0. If there is not any index of array a[] at any time such that a[index] <= x .we simply assign ans=-1 and print ans.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int binarysearch( int arr[], int N, int x)
{
int l = 0, r = N- 1, index = -1;
while (l <= r) {
int mid = (l + r) / 2;
if (arr[mid] <= x) {
index = mid ;
l = mid + 1;
}
else {
r = mid - 1;
}
}
return index;
}
int power_of_two( int n, int a[], int x)
{
int ans=0;
while (x!=0)
{
int index = binarysearch(a , n, x);
if (index == -1)
{
ans=-1; break ;
}
else {
x =x- a[index]; ans++;
}
}
return ans;
}
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;
}
|
Java
public class Main {
static int binarysearch( int [] arr, int N, int x) {
int l = 0 , r = N - 1 , index = - 1 ;
while (l <= r) {
int mid = (l + r) / 2 ;
if (arr[mid] <= x) {
index = mid;
l = mid + 1 ;
} else {
r = mid - 1 ;
}
}
return index;
}
static int power_of_two( int n, int [] a, int x) {
int ans = 0 ;
while (x != 0 ) {
int index = binarysearch(a, n, x);
if (index == - 1 ) {
ans = - 1 ;
break ;
} else {
x -= a[index];
ans += 1 ;
}
}
return ans;
}
public static void main(String[] args) {
int [] arr = { 2 , 2 , 4 , 4 , 8 };
int x = 6 ;
int n = arr.length;
System.out.println(power_of_two(n, arr, x));
}
}
|
Python3
def binarysearch(arr, N, x):
l, r, index = 0 , N - 1 , - 1
while l < = r:
mid = (l + r) / / 2
if arr[mid] < = x:
index = mid
l = mid + 1
else :
r = mid - 1
return index
def power_of_two(n, a, x):
ans = 0
while x ! = 0 :
index = binarysearch(a, n, x)
if index = = - 1 :
ans = - 1
break
else :
x - = a[index]
ans + = 1
return ans
if __name__ = = '__main__' :
arr = [ 2 , 2 , 4 , 4 , 8 ]
x = 6
n = len (arr)
print (power_of_two(n, arr, x))
|
C#
using System;
class Gfg
{
static int binarysearch( int [] arr, int N, int x)
{
int l = 0, r = N - 1, index = -1;
while (l <= r)
{
int mid = (l + r) / 2;
if (arr[mid] <= x)
{
index = mid;
l = mid + 1;
}
else
{
r = mid - 1;
}
}
return index;
}
static int power_of_two( int n, int [] a, int x)
{
int ans = 0;
while (x != 0)
{
int index = binarysearch(a, n, x);
if (index == -1)
{
ans = -1; break ;
}
else
{
x -= a[index]; ans++;
}
}
return ans;
}
static void Main( string [] args)
{
int [] arr = { 2, 2, 4, 4, 8 };
int x = 6;
int n = arr.Length;
Console.WriteLine(power_of_two(n, arr, x));
}
}
|
Javascript
function binarysearch(arr, N, x) {
let l = 0;
let r = N-1;
let index = -1;
while (l <= r) {
let mid = Math.trunc((l + r) / 2);
if (arr[mid] <= x) {
index = mid;
l = mid + 1;
}
else {
r = mid - 1;
}
}
return index;
}
function power_of_two(n, a, x) {
let ans = 0;
while (x != 0) {
let index = binarysearch(a, n, x);
if (index == -1) {
ans = -1;
break ;
}
else {
x -= a[index];
ans += 1;
}
}
return ans;
}
let arr = [2, 2, 4, 4, 8];
let x = 6;
let n = arr.length;
console.log(power_of_two(n, arr, x));
|
Time Complexity: O(x*logn) because binary search has a time complexity of O(logn)
Auxiliary Space: O(1)
Another Approach(Dynamic Programming.): We can define dp[i] as the minimum number of powers of 2 required to represent the number i.
Algorithm:
- Create an array dp of size x+1 to store the minimum number of powers of 2 required to represent each number from 0 to x.
- Initialize dp[0] to 0 since we don’t need any powers of 2 and to represent 0 and use a nested loop to iterate over each number i from 1 to x, and for each i, iterate over each power of 2 in the array arr and that is less than or equal to i.
- Calculate the minimum number of powers of 2 required to represent the difference i – arr[j], and add 1 to this to get the minimum number of powers of 2 required to represent i.
- Store this value in dp[i] and finally, return dp[x] if it is less than or equal to x and indicating that it is possible to represent x using the given array elements, otherwise return -1.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int min_powers_of_2( int arr[], int n, int x) {
int dp[x+1];
dp[0] = 0;
for ( int i = 1; i <= x; i++) {
dp[i] = INT_MAX;
for ( int j = 0; j < n; j++) {
if (arr[j] <= i) {
int sub_res = dp[i - arr[j]];
if (sub_res != INT_MAX) {
dp[i] = min(dp[i], sub_res + 1);
}
}
}
}
return dp[x] == INT_MAX ? -1 : dp[x];
}
int main() {
int arr[] = {2, 2, 4, 4, 8};
int n = sizeof (arr) / sizeof (arr[0]);
int x = 6;
int result = min_powers_of_2(arr, n, x);
cout << result << endl;
return 0;
}
|
Java
public class Main {
public static int minPowersOf2( int [] arr, int n, int x)
{
int [] dp = new int [x + 1 ];
dp[ 0 ] = 0 ;
for ( int i = 1 ; i <= x; i++) {
dp[i] = Integer.MAX_VALUE;
for ( int j = 0 ; j < n; j++) {
if (arr[j] <= i) {
int subRes = dp[i - arr[j]];
if (subRes != Integer.MAX_VALUE) {
dp[i] = Math.min(dp[i], subRes + 1 );
}
}
}
}
if (dp[x] == Integer.MAX_VALUE) {
return - 1 ;
}
else {
return dp[x];
}
}
public static void main(String[] args)
{
int [] arr = { 2 , 2 , 4 , 4 , 8 };
int n = arr.length;
int x = 6 ;
int result = minPowersOf2(arr, n, x);
System.out.println(result);
}
}
|
Python3
import sys
def min_powers_of_2(arr, n, x):
dp = [sys.maxsize] * (x + 1 )
dp[ 0 ] = 0
for i in range ( 1 , x + 1 ):
for j in range (n):
if arr[j] < = i:
sub_res = dp[i - arr[j]]
if sub_res ! = sys.maxsize:
dp[i] = min (dp[i], sub_res + 1 )
return - 1 if dp[x] = = sys.maxsize else dp[x]
if __name__ = = '__main__' :
arr = [ 2 , 2 , 4 , 4 , 8 ]
n = len (arr)
x = 6
result = min_powers_of_2(arr, n, x)
print (result)
|
C#
using System;
namespace MinPowersOf2Example
{
class Program
{
static int MinPowersOf2( int [] arr, int n, int x)
{
int [] dp = new int [x + 1];
dp[0] = 0;
for ( int i = 1; i <= x; i++)
{
dp[i] = int .MaxValue;
for ( int j = 0; j < n; j++)
{
if (arr[j] <= i)
{
int sub_res = dp[i - arr[j]];
if (sub_res != int .MaxValue)
{
dp[i] = Math.Min(dp[i], sub_res + 1);
}
}
}
}
return dp[x] == int .MaxValue ? -1 : dp[x];
}
static void Main( string [] args)
{
int [] arr = { 2, 2, 4, 4, 8 };
int n = arr.Length;
int x = 6;
int result = MinPowersOf2(arr, n, x);
Console.WriteLine(result);
}
}
}
|
Javascript
function minPowersOf2(arr, n, x) {
const dp = Array(x + 1).fill(Number.MAX_SAFE_INTEGER);
dp[0] = 0;
for (let i = 1; i <= x; i++) {
for (let j = 0; j < n; j++) {
if (arr[j] <= i) {
const subResult = dp[i - arr[j]];
if (subResult !== Number.MAX_SAFE_INTEGER) {
dp[i] = Math.min(dp[i], subResult + 1);
}
}
}
}
return dp[x] === Number.MAX_SAFE_INTEGER ? -1 : dp[x];
}
function main() {
const arr = [2, 2, 4, 4, 8];
const n = arr.length;
const x = 6;
const result = minPowersOf2(arr, n, x);
console.log(result);
}
main();
|
Time Complexity: O(nx), where n is the size of the array and x is the given number to be represented. This is because we are iterating over each number from 1 to x, and for each number, we are iterating over each element in the array arr that is less than or equal to that number.
Auxiliary Space: O(x), because we are creating an array dp of size x+1 to store the minimum number of powers of 2 required to represent each number from 0 to x.
Share your thoughts in the comments
Please Login to comment...