Maximum subset sum such that no two elements in set have same digit in them
Last Updated :
18 Apr, 2023
Given an array of N elements. Find the subset of elements which has maximum sum such that no two elements in the subset has common digit present in them.
Examples:
Input : array[] = {22, 132, 4, 45, 12, 223}
Output : 268
Maximum Sum Subset will be = {45, 223} .
All possible digits are present except 1.
But to include 1 either 2 or both 2 and 3 have
to be removed which result in smaller sum value.
Input : array[] = {1, 21, 32, 4, 5 }
Output : 42
- Here we can use Dynamic Programming and Bit Masking to solve this question.
- Consider a 10-bit representation of every number where each bit is 1 if digit corresponding to that bit is present in that number.
- Now maintain a dp[i], which stores the maximum possible sum which can be achieved with all those digits present in the set, corresponding to the bit positions which are 1 in Binary Representation of i.
- Recurrence Relation will be of the form dp[i] = max(dp[i], dp[i^mask] + a[j]) , for all those j from 1 to n such that mask (10-bit Representation of a[j]) satisfy i || mask = i. (Since then only we can assure that all digit available in i are satisfied).
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int dp[1024];
int get_binary( int u)
{
int ans = 0;
while (u) {
int rem = u % 10;
ans |= (1 << rem);
u /= 10;
}
return ans;
}
int recur( int u, int array[], int n)
{
if (u == 0)
return 0;
if (dp[u] != -1)
return dp[u];
int temp = 0;
for ( int i = 0; i < n; i++) {
int mask = get_binary(array[i]);
if ((mask | u) == u) {
dp[u] = max(max(0,
dp[u ^ mask]) + array[i], dp[u]);
}
}
return dp[u];
}
int solve( int array[], int n)
{
for ( int i = 0; i < (1 << 10); i++) {
dp[i] = -1;
}
int ans = 0;
for ( int i = 0; i < (1 << 10); i++) {
ans = max(ans, recur(i, array, n));
}
return ans;
}
int main()
{
int array[] = { 22, 132, 4, 45, 12, 223 };
int n = sizeof (array) / sizeof (array[0]);
cout << solve(array, n);
}
|
Java
import java.io.*;
class GFG
{
static int []dp = new int [ 1024 ];
static int get_binary( int u)
{
int ans = 0 ;
while (u > 0 )
{
int rem = u % 10 ;
ans |= ( 1 << rem);
u /= 10 ;
}
return ans;
}
static int recur( int u, int []array, int n)
{
if (u == 0 )
return 0 ;
if (dp[u] != - 1 )
return dp[u];
for ( int i = 0 ; i < n; i++)
{
int mask = get_binary(array[i]);
if ((mask | u) == u)
{
dp[u] = Math.max(Math.max( 0 ,
dp[u ^ mask]) + array[i], dp[u]);
}
}
return dp[u];
}
static int solve( int []array, int n)
{
for ( int i = 0 ; i < ( 1 << 10 ); i++)
{
dp[i] = - 1 ;
}
int ans = 0 ;
for ( int i = 0 ; i < ( 1 << 10 ); i++)
{
ans = Math.max(ans, recur(i, array, n));
}
return ans;
}
static public void main (String[] args)
{
int []array = { 22 , 132 , 4 , 45 , 12 , 223 };
int n = array.length;
System.out.println(solve(array, n));
}
}
|
Python3
dp = [ 0 ] * 1024 ;
def get_binary(u) :
ans = 0 ;
while (u) :
rem = u % 10 ;
ans | = ( 1 << rem);
u / / = 10 ;
return ans;
def recur(u, array, n) :
if (u = = 0 ) :
return 0 ;
if (dp[u] ! = - 1 ) :
return dp[u];
temp = 0 ;
for i in range (n) :
mask = get_binary(array[i]);
if ((mask | u) = = u) :
dp[u] = max ( max ( 0 , dp[u ^ mask]) + array[i], dp[u]);
return dp[u];
def solve(array, n) :
i = 0
while (i < ( 1 << 10 )) :
dp[i] = - 1 ;
i + = 1
ans = 0 ;
i = 0
while (i < ( 1 << 10 )) :
ans = max (ans, recur(i, array, n));
i + = 1
return ans;
if __name__ = = "__main__" :
array = [ 22 , 132 , 4 , 45 , 12 , 223 ] ;
n = len (array);
print (solve(array, n));
|
Javascript
<script>
let dp = new Array(1024);
dp.fill(-1);
function get_binary(u)
{
let ans = 0;
while (u > 0)
{
let rem = u % 10;
ans |= (1 << rem);
u = parseInt(u / 10, 10);
}
return ans;
}
function recur(u, array, n)
{
if (u == 0)
return 0;
if (dp[u] != -1)
return dp[u];
for (let i = 0; i < n; i++)
{
let mask = get_binary(array[i]);
if ((mask | u) == u)
{
dp[u] = Math.max(Math.max(0,
dp[u ^ mask]) + array[i], dp[u]);
}
}
return dp[u];
}
function solve(array, n)
{
for (let i = 0; i < (1 << 10); i++)
{
dp[i] = -1;
}
let ans = 0;
for (let i = 0; i < (1 << 10); i++)
{
ans = Math.max(ans, recur(i, array, n));
}
return ans;
}
let array = [ 22, 132, 4, 45, 12, 223 ];
let n = array.length;
document.write(solve(array, n));
</script>
|
C#
using System;
class GFG
{
static int []dp = new int [1024];
static int get_binary( int u)
{
int ans = 0;
while (u > 0)
{
int rem = u % 10;
ans |= (1 << rem);
u /= 10;
}
return ans;
}
static int recur( int u, int []array, int n)
{
if (u == 0)
return 0;
if (dp[u] != -1)
return dp[u];
for ( int i = 0; i < n; i++)
{
int mask = get_binary(array[i]);
if ((mask | u) == u)
{
dp[u] = Math.Max(Math.Max(0,
dp[u ^ mask]) + array[i], dp[u]);
}
}
return dp[u];
}
static int solve( int []array, int n)
{
for ( int i = 0; i < (1 << 10); i++)
{
dp[i] = -1;
}
int ans = 0;
for ( int i = 0; i < (1 << 10); i++)
{
ans = Math.Max(ans, recur(i, array, n));
}
return ans;
}
static public void Main ()
{
int []array = { 22, 132, 4, 45, 12, 223 };
int n = array.Length;
Console.WriteLine (solve(array, n));
}
}
|
Time Complexity : O(N*(2^10))
Auxiliary Space: O(1024)
Efficient approach : Using DP Tabulation method ( Iterative approach )
The approach to solve this problem is same but DP tabulation(bottom-up) method is better then Dp + memoization(top-down) because memoization method needs extra stack space of recursion calls.
Steps to solve this problem :
- Create a DP to store the solution of the subproblems.
- Initialize the DP with base cases.
- Now Iterate over subproblems to get the value of current problem form previous computation of subproblems stored in DP.
- Create a variable ans to store the final result.
- Iterate over Dp and update ans.
- At last return and print ans.
Implementation :
C++
#include <bits/stdc++.h>
using namespace std;
int dp[1024];
int get_binary( int u)
{
int ans = 0;
while (u) {
int rem = u % 10;
ans |= (1 << rem);
u /= 10;
}
return ans;
}
int solve( int array[], int n)
{
for ( int i = 0; i < (1 << 10); i++) {
dp[i] = 0;
}
for ( int i = 0; i < n; i++) {
int mask = get_binary(array[i]);
for ( int j = (1 << 10) - 1; j >= 0; j--) {
if ((mask | j) == j) {
dp[j] = max(dp[j], dp[j ^ mask] + array[i]);
}
}
}
int ans = 0;
for ( int i = 0; i < (1 << 10); i++) {
ans = max(ans, dp[i]);
}
return ans;
}
int main()
{
int array[] = { 22, 132, 4, 45, 12, 223 };
int n = sizeof (array) / sizeof (array[0]);
cout << solve(array, n);
}
|
Java
import java.util.Arrays;
class GFG {
static int dp[] = new int [ 1024 ];
static int get_binary( int u)
{
int ans = 0 ;
while (u != 0 ) {
int rem = u % 10 ;
ans |= ( 1 << rem);
u /= 10 ;
}
return ans;
}
static int solve( int array[], int n)
{
Arrays.fill(dp, 0 );
for ( int i = 0 ; i < n; i++) {
int mask = get_binary(array[i]);
for ( int j = ( 1 << 10 ) - 1 ; j >= 0 ; j--) {
if ((mask | j) == j) {
dp[j] = Math.max(dp[j], dp[j ^ mask]
+ array[i]);
}
}
}
int ans = 0 ;
for ( int i = 0 ; i < ( 1 << 10 ); i++) {
ans = Math.max(ans, dp[i]);
}
return ans;
}
public static void main(String[] args)
{
int array[] = { 22 , 132 , 4 , 45 , 12 , 223 };
int n = array.length;
System.out.println(solve(array, n));
}
}
|
Python3
def get_binary(u):
ans = 0
while u:
rem = u % 10
ans | = ( 1 << rem)
u / / = 10
return ans
def solve(array, n):
dp = [ 0 ] * ( 1 << 10 )
for i in range (n):
mask = get_binary(array[i])
for j in range (( 1 << 10 ) - 1 , - 1 , - 1 ):
if (mask | j) = = j:
dp[j] = max (dp[j], dp[j ^ mask] + array[i])
ans = 0
for i in range ( 1 << 10 ):
ans = max (ans, dp[i])
return ans
array = [ 22 , 132 , 4 , 45 , 12 , 223 ]
n = len (array)
print (solve(array, n))
|
C#
using System;
class Program
{
static int [] dp = new int [1024];
static int GetBinary( int u)
{
int ans = 0;
while (u != 0)
{
int rem = u % 10;
ans |= (1 << rem);
u /= 10;
}
return ans;
}
static int Solve( int [] array, int n)
{
for ( int i = 0; i < (1 << 10); i++)
{
dp[i] = 0;
}
for ( int i = 0; i < n; i++)
{
int mask = GetBinary(array[i]);
for ( int j = (1 << 10) - 1; j >= 0; j--)
{
if ((mask | j) == j)
{
dp[j] = Math.Max(dp[j], dp[j ^ mask] + array[i]);
}
}
}
int ans = 0;
for ( int i = 0; i < (1 << 10); i++)
{
ans = Math.Max(ans, dp[i]);
}
return ans;
}
static void Main()
{
int [] array = { 22, 132, 4, 45, 12, 223 };
int n = array.Length;
Console.WriteLine(Solve(array, n));
}
}
|
Javascript
function getBinary(u) {
let ans = 0;
while (u) {
let rem = u % 10;
ans |= (1 << rem);
u = Math.floor(u / 10);
}
return ans;
}
function solve(array, n) {
let dp = new Array(1 << 10).fill(0);
for (let i = 0; i < n; i++) {
let mask = getBinary(array[i]);
for (let j = (1 << 10) - 1; j >= 0; j--) {
if ((mask | j) == j) {
dp[j] = Math.max(dp[j], dp[j ^ mask] + array[i]);
}
}
}
let ans = 0;
for (let i = 0; i < 1 << 10; i++) {
ans = Math.max(ans, dp[i]);
}
return ans;
}
let array = [22, 132, 4, 45, 12, 223];
let n = array.length;
console.log(solve(array, n));
|
Output
268
Time Complexity : O(N*(2^10))
Auxiliary Space: O(2^10)
Share your thoughts in the comments
Please Login to comment...