Bit Toggling to Minimize Array Sum
Last Updated :
04 Dec, 2023
Given an array arr[] consisting of positive integers of size N. the task is to minimize the overall sum of arr[] by toggling the unset bit (0 bit) of any element of the array for T times, where T is the total number of set bits over all the elements of arr[].
Note: In case of 32-bit integer overflow, return (overall Sum % 1e9 + 7).
Examples:
Input: arr = {2, 2, 2};
Output: 21
Explanation: Binary representation 2 is 10. Since there are total 3 set bit. so, we need to set 3 bits, we can set the lowest unset bits of the every 2s such that they become 11. The total sum is then 3 + 3 + 3 = 9.
Input: arr = {3, 3, 7}
Output: 77
Bit Toggling to Minimize Array Sum Using Greedy Technique:
We can use the greedy technique here, we’ll change the rightmost 0s to 1s.
Step-by-step approach:
- Iterate over the elements of the array and count the total set bit T.
- Again, Iterate over the elements of the array
- Convert the element into its binary representation and iterate over the bits of binary representation.
- Check for its ith bit is unset or not.
- If the ith bit is unset then, Push the ith position into the array smallestUnsetBit[].
- Sort the smallestUnsetBit[] array.
- Iterate over the smallestUnsetBit[] for T time and calculate the value for smallestUnsetBit[i] by 2smallestUnsetBit[i] , this value will contribute into the overallSum after toggling smallestUnsetBit[i] bit.
- Return the overallSum.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
#define mod (1e9 + 7)
int minSum(vector< int >& nums)
{
int T = 0;
for ( int i : nums) {
T += __builtin_popcount(i);
}
vector< int > smallestUnsetBit;
for ( auto num : nums) {
string s = bitset<31>(num).to_string();
for ( int i = 30; i >= 0; i--) {
if (s[i] == '0' ) {
smallestUnsetBit.push_back(30 - i);
}
}
}
sort(smallestUnsetBit.begin(), smallestUnsetBit.end());
long long result
= accumulate(nums.begin(), nums.end(), 0LL);
int i = 0;
while (T--) {
result
= (result
+ ( long long ) pow (2, smallestUnsetBit[i++]))
% ( long long )mod;
}
return result % ( long long )mod;
}
int main()
{
vector< int > arr = { 2, 2, 2 };
int result = minSum(arr);
cout << result << endl;
return 0;
}
|
Java
import java.util.*;
import java.util.stream.*;
public class Main {
static final int MOD = ( int )1e9 + 7 ;
public static int minSum(List<Integer> nums)
{
int T = 0 ;
for ( int i : nums) {
T += Integer.bitCount(i);
}
List<Integer> smallestUnsetBit = new ArrayList<>();
for ( int num : nums) {
String s
= String
.format( "%31s" ,
Integer.toBinaryString(num))
.replace( ' ' , '0' );
for ( int i = 30 ; i >= 0 ; i--) {
if (s.charAt(i) == '0' ) {
smallestUnsetBit.add( 30 - i);
}
}
}
Collections.sort(smallestUnsetBit);
long result = nums.stream()
.mapToLong(Integer::longValue)
.sum();
int i = 0 ;
for ( int j = 0 ; j < T; j++) {
result = (result
+ ( long )Math.pow(
2 , smallestUnsetBit.get(i++)))
% MOD;
}
return ( int )(result % MOD);
}
public static void main(String[] args)
{
List<Integer> arr = Arrays.asList( 2 , 2 , 2 );
int result = minSum(arr);
System.out.println(result);
}
}
|
Python3
def minSum(nums):
mod = int ( 1e9 + 7 )
T = 0
for num in nums:
T + = bin (num).count( '1' )
smallestUnsetBit = []
for num in nums:
s = format (num, '031b' )
for i in range ( 30 , - 1 , - 1 ):
if s[i] = = '0' :
smallestUnsetBit.append( 30 - i)
smallestUnsetBit.sort()
result = sum (nums)
i = 0
while T > 0 :
result = (result + 2 * * smallestUnsetBit[i]) % mod
i + = 1
T - = 1
return result % mod
if __name__ = = "__main__" :
arr = [ 2 , 2 , 2 ]
result = minSum(arr)
print (result)
|
C#
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static int Mod = 1000000007;
static int MinSum(List< int > nums)
{
int T = 0;
foreach ( int num in nums)
{
T += BitCount(num);
}
List< int > smallestUnsetBit = new List< int >();
foreach ( var num in nums)
{
string s = Convert.ToString(num, 2).PadLeft(31, '0' );
for ( int j = 30; j >= 0; j--)
{
if (s[j] == '0' )
{
smallestUnsetBit.Add(30 - j);
}
}
}
smallestUnsetBit.Sort();
long result = nums.Sum(x => ( long )x);
int index = 0;
while (T-- > 0)
{
result = (result + ( long )Math.Pow(2, smallestUnsetBit[index++])) % Mod;
}
return ( int )(result % Mod);
}
static int BitCount( int n)
{
int count = 0;
while (n > 0)
{
n &= (n - 1);
count++;
}
return count;
}
static void Main( string [] args)
{
List< int > arr = new List< int > { 2, 2, 2 };
int result = MinSum(arr);
Console.WriteLine(result);
}
}
|
Javascript
const mod = 1e9 + 7;
function minSum(nums) {
let T = 0;
for (let i of nums) {
T += i.toString(2).split( '1' ).length - 1;
}
let smallestUnsetBit = [];
for (let num of nums) {
let s = num.toString(2).padStart(31, '0' );
for (let i = 30; i >= 0; i--) {
if (s[i] === '0' ) {
smallestUnsetBit.push(30 - i);
}
}
}
smallestUnsetBit.sort((a, b) => a - b);
let result = nums.reduce((acc, curr) => acc + curr, 0);
let i = 0;
while (T--) {
result = (result + 2 ** smallestUnsetBit[i++]) % mod;
}
return result % mod;
}
let arr = [2, 2, 2];
let result = minSum(arr);
console.log(result);
|
Time Complexity: O(N), where N is the length of the given array
Auxiliary Space: O(N)
Share your thoughts in the comments
Please Login to comment...