Python Program for Subset Sum Problem | DP-25
Write a Python program for a given set of non-negative integers and a value sum, the task is to check if there is a subset of the given set whose sum is equal to the given sum.
Examples:
Input: set[] = {3, 34, 4, 12, 5, 2}, sum = 9
Output: True
Explanation: There is a subset (4, 5) with sum 9.Input: set[] = {3, 34, 4, 12, 5, 2}, sum = 30
Output: False
Explanation: There is no subset that adds up to 30.
Python Program for Subset Sum Problem using Recursion:
For the recursive approach, there will be two cases.
- Consider the ‘last’ element to be a part of the subset. Now the new required sum = required sum – value of ‘last’ element.
- Don’t include the ‘last’ element in the subset. Then the new required sum = old required sum.
In both cases, the number of available elements decreases by 1.
Step-by-step approach:
- Build a recursive function and pass the index to be considered (here gradually moving from the last end) and the remaining sum amount.
- For each index check the base cases and utilize the above recursive call.
- If the answer is true for any recursion call, then there exists such a subset. Otherwise, no such subset exists.
Below is the implementation of the above approach.
Python3
# A recursive solution for subset sum # problem # Returns true if there is a subset # of set[] with sun equal to given sum def isSubsetSum( set , n, sum ): # Base Cases if ( sum = = 0 ): return True if (n = = 0 ): return False # If last element is greater than # sum, then ignore it if ( set [n - 1 ] > sum ): return isSubsetSum( set , n - 1 , sum ) # Else, check if sum can be obtained # by any of the following # (a) including the last element # (b) excluding the last element return isSubsetSum( set , n - 1 , sum ) or isSubsetSum( set , n - 1 , sum - set [n - 1 ]) # Driver code if __name__ = = '__main__' : set = [ 3 , 34 , 4 , 12 , 5 , 2 ] sum = 9 n = len ( set ) if (isSubsetSum( set , n, sum ) = = True ): print ( "Found a subset with given sum" ) else : print ( "No subset with given sum" ) # This code is contributed by Nikita Tiwari. |
Found a subset with given sum
Time Complexity: O(2n)
Auxiliary space: O(n)
Python Program for Subset Sum Problem using Memoization:
As seen in the previous recursion method, each state of the solution can be uniquely identified using two variables – the index and the remaining sum. So create a 2D array to store the value of each state to avoid recalculation of the same state.
Below is the implementation of the above approach:
Python3
# Python program for the above approach # Taking the matrix as globally tab = [[ - 1 for i in range ( 2000 )] for j in range ( 2000 )] # Check if possible subset with # given sum is possible or not def subsetSum(a, n, sum ): # If the sum is zero it means # we got our expected sum if ( sum = = 0 ): return 1 if (n < = 0 ): return 0 # If the value is not -1 it means it # already call the function # with the same value. # it will save our from the repetition. if (tab[n - 1 ][ sum ] ! = - 1 ): return tab[n - 1 ][ sum ] # If the value of a[n-1] is # greater than the sum. # we call for the next value if (a[n - 1 ] > sum ): tab[n - 1 ][ sum ] = subsetSum(a, n - 1 , sum ) return tab[n - 1 ][ sum ] else : # Here we do two calls because we # don't know which value is # full-fill our criteria # that's why we doing two calls tab[n - 1 ][ sum ] = subsetSum(a, n - 1 , sum ) return tab[n - 1 ][ sum ] or subsetSum(a, n - 1 , sum - a[n - 1 ]) # Driver Code if __name__ = = '__main__' : n = 5 a = [ 1 , 5 , 3 , 7 , 4 ] sum = 12 if (subsetSum(a, n, sum )): print ( "YES" ) else : print ( "NO" ) # This code is contributed by shivani. |
YES
Time Complexity: O(sum*n)
Auxiliary space: O(n)
Python Program for Subset Sum Problem using Dynamic Programming:
We can solve the problem in Pseudo-polynomial time we can use the Dynamic programming approach.
So we will create a 2D array of size (n + 1) * (sum + 1) of type boolean. The state dp[i][j] will be true if there exists a subset of elements from set[0 . . . i] with sum value = ‘j’.
The dynamic programming relation is as follows:
if (A[i-1] > j)
dp[i][j] = dp[i-1][j]
else
dp[i][j] = dp[i-1][j] OR dp[i-1][j-set[i-1]]
Below is the implementation of the above approach:
Python3
# A Dynamic Programming solution for subset # sum problem Returns true if there is a subset of # set[] with sun equal to given sum # Returns true if there is a subset of set[] # with sum equal to given sum def isSubsetSum( set , n, sum ): # The value of subset[i][j] will be # true if there is a # subset of set[0..j-1] with sum equal to i subset = ([[ False for i in range ( sum + 1 )] for i in range (n + 1 )]) # If sum is 0, then answer is true for i in range (n + 1 ): subset[i][ 0 ] = True # If sum is not 0 and set is empty, # then answer is false for i in range ( 1 , sum + 1 ): subset[ 0 ][i] = False # Fill the subset table in bottom up manner for i in range ( 1 , n + 1 ): for j in range ( 1 , sum + 1 ): if j < set [i - 1 ]: subset[i][j] = subset[i - 1 ][j] if j > = set [i - 1 ]: subset[i][j] = (subset[i - 1 ][j] or subset[i - 1 ][j - set [i - 1 ]]) return subset[n][ sum ] # Driver code if __name__ = = '__main__' : set = [ 3 , 34 , 4 , 12 , 5 , 2 ] sum = 9 n = len ( set ) if (isSubsetSum( set , n, sum ) = = True ): print ( "Found a subset with given sum" ) else : print ( "No subset with given sum" ) # This code is contributed by # sahil shelangia. |
Found a subset with given sum
Time Complexity: O(sum * n), where n is the size of the array.
Auxiliary Space: O(sum*n), as the size of the 2-D array is sum*n.
Python Program for Subset Sum Problem using Dynamic Programming with space optimization to linear:
In previous approach of dynamic programming we have derive the relation between states as given below:
if (A[i-1] > j)
dp[i][j] = dp[i-1][j]
else
dp[i][j] = dp[i-1][j] OR dp[i-1][j-set[i-1]]
If we observe that for calculating current dp[i][j] state we only need previous row dp[i-1][j] or dp[i-1][j-set[i-1]].
There is no need to store all the previous states just one previous state is used to compute result.
Step-by-step approach:
- Define two arrays prev and curr of size Sum+1 to store the just previous row result and current row result respectively.
- Once curr array is calculated then curr becomes our prev for the next row.
- When all rows are processed the answer is stored in prev array.
Below is the implementation of the above approach:
Python3
# Returns True if there is a subset of set[] # with a sum equal to the given sum def isSubsetSum(nums, n, sum ): # Create a list to store the previous row result prev = [ False ] * ( sum + 1 ) # If sum is 0, then the answer is True prev[ 0 ] = True # If sum is not 0 and the set is empty, # then the answer is False for i in range ( 1 , n + 1 ): curr = [ False ] * ( sum + 1 ) for j in range ( 1 , sum + 1 ): if j < nums[i - 1 ]: curr[j] = prev[j] if j > = nums[i - 1 ]: curr[j] = prev[j] or prev[j - nums[i - 1 ]] # Now curr becomes prev for (i+1)-th element prev = curr return prev[ sum ] # Driver code if __name__ = = "__main__" : nums = [ 3 , 34 , 4 , 12 , 5 , 2 ] sum_value = 9 n = len (nums) if isSubsetSum(nums, n, sum_value): print ( "Found a subset with the given sum" ) else : print ( "No subset with the given sum" ) |
Found a subset with given sum
Time Complexity: O(sum * n), where n is the size of the array.
Auxiliary Space: O(sum), as the size of the 1-D array is sum+1.
Please refer complete article on Subset Sum Problem | DP-25 for more details!