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++
// C++ implementation of above approach #include <bits/stdc++.h> using namespace std; int dp[1024]; // Function to create mask for every number int get_binary( int u) { int ans = 0; while (u) { int rem = u % 10; ans |= (1 << rem); u /= 10; } return ans; } // Recursion for Filling DP array int recur( int u, int array[], int n) { // Base Condition 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]); // Recurrence Relation if ((mask | u) == u) { dp[u] = max(max(0, dp[u ^ mask]) + array[i], dp[u]); } } return dp[u]; } // Function to find Maximum Subset Sum int solve( int array[], int n) { // Initialize DP array for ( int i = 0; i < (1 << 10); i++) { dp[i] = -1; } int ans = 0; // Iterate over all possible masks of 10 bit number for ( int i = 0; i < (1 << 10); i++) { ans = max(ans, recur(i, array, n)); } return ans; } // Driver Code int main() { int array[] = { 22, 132, 4, 45, 12, 223 }; int n = sizeof (array) / sizeof (array[0]); cout << solve(array, n); } |
Java
// Java implementation of above approach import java.io.*; class GFG { static int []dp = new int [ 1024 ]; // Function to create mask for every number static int get_binary( int u) { int ans = 0 ; while (u > 0 ) { int rem = u % 10 ; ans |= ( 1 << rem); u /= 10 ; } return ans; } // Recursion for Filling DP array static int recur( int u, int []array, int n) { // Base Condition 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]); // Recurrence Relation if ((mask | u) == u) { dp[u] = Math.max(Math.max( 0 , dp[u ^ mask]) + array[i], dp[u]); } } return dp[u]; } // Function to find Maximum Subset Sum static int solve( int []array, int n) { // Initialize DP array for ( int i = 0 ; i < ( 1 << 10 ); i++) { dp[i] = - 1 ; } int ans = 0 ; // Iterate over all possible masks of 10 bit number for ( int i = 0 ; i < ( 1 << 10 ); i++) { ans = Math.max(ans, recur(i, array, n)); } return ans; } // Driver Code static public void main (String[] args) { int []array = { 22 , 132 , 4 , 45 , 12 , 223 }; int n = array.length; System.out.println(solve(array, n)); } } // This code is contributed by anuj_67.. |
Python3
# Python3 implementation of above approach dp = [ 0 ] * 1024 ; # Function to create mask for every number def get_binary(u) : ans = 0 ; while (u) : rem = u % 10 ; ans | = ( 1 << rem); u / / = 10 ; return ans; # Recursion for Filling DP array def recur(u, array, n) : # Base Condition if (u = = 0 ) : return 0 ; if (dp[u] ! = - 1 ) : return dp[u]; temp = 0 ; for i in range (n) : mask = get_binary(array[i]); # Recurrence Relation if ((mask | u) = = u) : dp[u] = max ( max ( 0 , dp[u ^ mask]) + array[i], dp[u]); return dp[u]; # Function to find Maximum Subset Sum def solve(array, n) : i = 0 # Initialize DP array while (i < ( 1 << 10 )) : dp[i] = - 1 ; i + = 1 ans = 0 ; i = 0 # Iterate over all possible masks of 10 bit number while (i < ( 1 << 10 )) : ans = max (ans, recur(i, array, n)); i + = 1 return ans; # Driver Code if __name__ = = "__main__" : array = [ 22 , 132 , 4 , 45 , 12 , 223 ] ; n = len (array); print (solve(array, n)); # This code is contributed by AnkitRai01 |
Javascript
<script> // Javascript implementation of above approach let dp = new Array(1024); dp.fill(-1); // Function to create mask for every number function get_binary(u) { let ans = 0; while (u > 0) { let rem = u % 10; ans |= (1 << rem); u = parseInt(u / 10, 10); } return ans; } // Recursion for Filling DP array function recur(u, array, n) { // Base Condition 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]); // Recurrence Relation if ((mask | u) == u) { dp[u] = Math.max(Math.max(0, dp[u ^ mask]) + array[i], dp[u]); } } return dp[u]; } // Function to find Maximum Subset Sum function solve(array, n) { // Initialize DP array for (let i = 0; i < (1 << 10); i++) { dp[i] = -1; } let ans = 0; // Iterate over all possible masks of 10 bit number 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#
// C# implementation of above approach using System; class GFG { static int []dp = new int [1024]; // Function to create mask for every number static int get_binary( int u) { int ans = 0; while (u > 0) { int rem = u % 10; ans |= (1 << rem); u /= 10; } return ans; } // Recursion for Filling DP array static int recur( int u, int []array, int n) { // Base Condition 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]); // Recurrence Relation if ((mask | u) == u) { dp[u] = Math.Max(Math.Max(0, dp[u ^ mask]) + array[i], dp[u]); } } return dp[u]; } // Function to find Maximum Subset Sum static int solve( int []array, int n) { // Initialize DP array for ( int i = 0; i < (1 << 10); i++) { dp[i] = -1; } int ans = 0; // Iterate over all possible masks of 10 bit number for ( int i = 0; i < (1 << 10); i++) { ans = Math.Max(ans, recur(i, array, n)); } return ans; } // Driver Code static public void Main () { int []array = { 22, 132, 4, 45, 12, 223 }; int n = array.Length; Console.WriteLine (solve(array, n)); } } // This code is contributed by ajit. |
268
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]; // Function to create mask for every number int get_binary( int u) { int ans = 0; while (u) { int rem = u % 10; ans |= (1 << rem); u /= 10; } return ans; } // Function to find Maximum Subset Sum int solve( int array[], int n) { // Initialize DP array for ( int i = 0; i < (1 << 10); i++) { dp[i] = 0; } // Fill DP table using bottom-up approach 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]); } } } // Find maximum sum from DP array int ans = 0; for ( int i = 0; i < (1 << 10); i++) { ans = max(ans, dp[i]); } return ans; } // Driver Code 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 ]; // Function to create mask for every number static int get_binary( int u) { int ans = 0 ; while (u != 0 ) { int rem = u % 10 ; ans |= ( 1 << rem); u /= 10 ; } return ans; } // Function to find Maximum Subset Sum static int solve( int array[], int n) { // Initialize DP array Arrays.fill(dp, 0 ); // Fill DP table using bottom-up approach 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]); } } } // Find maximum sum from DP array int ans = 0 ; for ( int i = 0 ; i < ( 1 << 10 ); i++) { ans = Math.max(ans, dp[i]); } return ans; } // Driver Code 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
# Function to create mask for every number def get_binary(u): ans = 0 while u: rem = u % 10 ans | = ( 1 << rem) u / / = 10 return ans # Function to find Maximum Subset Sum def solve(array, n): # Initialize DP array dp = [ 0 ] * ( 1 << 10 ) # Fill DP table using bottom-up approach 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]) # Find maximum sum from DP array ans = 0 for i in range ( 1 << 10 ): ans = max (ans, dp[i]) return ans # Driver Code 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]; // Function to create mask for every number static int GetBinary( int u) { int ans = 0; while (u != 0) { int rem = u % 10; ans |= (1 << rem); u /= 10; } return ans; } // Function to find Maximum Subset Sum static int Solve( int [] array, int n) { // Initialize DP array for ( int i = 0; i < (1 << 10); i++) { dp[i] = 0; } // Fill DP table using bottom-up approach 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]); } } } // Find maximum sum from DP array int ans = 0; for ( int i = 0; i < (1 << 10); i++) { ans = Math.Max(ans, dp[i]); } return ans; } // Driver Code static void Main() { int [] array = { 22, 132, 4, 45, 12, 223 }; int n = array.Length; Console.WriteLine(Solve(array, n)); } } |
Javascript
// Function to create mask for every number function getBinary(u) { let ans = 0; while (u) { let rem = u % 10; ans |= (1 << rem); u = Math.floor(u / 10); } return ans; } // Function to find Maximum Subset Sum function solve(array, n) { // Initialize DP array let dp = new Array(1 << 10).fill(0); // Fill DP table using bottom-up approach 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]); } } } // Find maximum sum from DP array let ans = 0; for (let i = 0; i < 1 << 10; i++) { ans = Math.max(ans, dp[i]); } return ans; } // Driver Code 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)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!