The “Sum of Subset” problem is a classic example of a combinatorial problem that can be solved using recursion. The objective is to determine whether a subset of the given set of numbers can be found that sums up to a specific target value. This problem is significant in computer science, particularly in the fields of algorithms and complexity theory, can be efficiently solved using Dynamic Programming (DP). Dynamic Programming is particularly useful for this problem as it helps to avoid redundant calculations seen in the pure recursive approach by storing the results of subproblems.
Dynamic Programming Approach:
- We create a 2D array
dp
where each elementdp[i][j]
represents whether there exists a subset of the firsti
numbers in the setS
that sums up toj
. - The dimensions of this array are
(n+1) x (sum+1)
, wheren
is the number of elements in the set andsum
is the target sum we’re trying to achieve. - The value of
dp[i][j]
istrue
if a subset exists with sumj
using the firsti
items, otherwisefalse
.
Initialization:
- The first column of
dp
, which represents the target sum0
, is initialized totrue
because the empty subset always sums to0
. - The first row, except for
dp[0][0]
, is initialized tofalse
because we cannot achieve a positive sum with zero elements.
Filling the DP Table:
- For each element
set[i-1]
, we determine whether to include it in the subset or not based on the values already computed and stored in the table.
Kotlin
fun isSubsetSum(set: IntArray, n: Int, sum: Int): Boolean {
// dp[i][j] will be true if there is a subset of set[0..i-1] with sum j
val dp = Array(n + 1) { BooleanArray(sum + 1) }
// Initialize top row as true, as 0 sum is possible with all elements.
for (i in 0..n) {
dp[i][0] = true
}
// Fill the subset table in a bottom-up manner
for (i in 1..n) {
for (j in 1..sum) {
// If the current element is more than the sum, we copy the value from the above row
if (set[i - 1] > j) dp[i][j] = dp[i - 1][j]
else {
// Include the element or exclude it
dp[i][j] = dp[i - 1][j] || dp[i - 1][j - set[i - 1]]
}
}
}
return dp[n][sum]
}
// Example usage
fun main() {
val set = intArrayOf(3, 34, 4, 12, 5, 2)
val sum = 9
val n = set.size
if (isSubsetSum(set, n, sum))
println("Found a subset with given sum")
else
println("No subset with given sum")
}
Explanation:
- The function
isSubsetSum
initializes a 2D Boolean arraydp
wheredp[i][j]
represents the existence of a subset with sumj
using the firsti
items of the set. - It first initializes all positions of
dp[i][0]
totrue
because a sum of0
can always be achieved with an empty subset. - The main nested loops fill the DP table. For each item
set[i-1]
and each target sumj
, it checks if the current item is greater thanj
. If it is, it copies the value from the previous row (excluding the current item). Otherwise, it checks if any of the two conditions (including or excluding the current item) can achieve the target sum. - The final answer to the problem is found at
dp[n][sum]
, which indicates whether a subset with the target sum exists within the entire set.