I was trying to write a dynamic programming algorithm using a bottom up approach that solves the subset sum problem's version where the solution can be either an empty set and the initial set can only contain positive integers.
The following is my implementation, but I am not sure it is correct for all cases.
def _get_subset_sum_matrix(subset, s):
m = [[0 for _ in range(s + 1)] for _ in range(len(subset) + 1)]
for i in range(1, s + 1):
m[0][i] = 0
for j in range(0, len(subset) + 1):
m[j][0] = 1
return m
def subset_sum(subset, s):
m = _get_subset_sum_matrix(subset, s)
for i in range(1, len(subset) + 1):
for j in range(1, s + 1):
if subset[i - 1] == j:
m[i][j] = 1
else:
# We can include the current element,
# because it is less than the current number j.
if subset[i - 1] <= j:
m[i][j] = max(m[i - 1][j], m[i - 1][j - subset[i - 1]])
else:
m[i][j] = m[i - 1][j]
return m[-1][-1]
You can imagine the idea of my algorithm as follows.
I have the numbers of the set in the vertical axis on the left, where the first element is actually the empty set. These numbers are not considered as only numbers, but, as I go down from the empty set (the first element), I start considering greater sets, that include all previous elements plus the current one.
Example, suppose I have the set S = {1, 2, 3}
. I first consider the empty set, then the union of the empty set and {1}
, then the union of {1}
and {2}
, and finally the union of {1, 2}
and {3}
.
In the horizontal axis you can imagine I have an increasing sequence of numbers up to the number we want to obtain (by summing the numbers of a certain subset of S
). Example, suppose we want to obtain 4, then the increasing sequence would be 0, 1, 2, 3, 4
.
So, I first start considering I want to obtain the number 0, and then 1, 2, etc, as it is usually done in a dynamic programming algorithm using a bottom-up approach.
Apart from the setup of the matrix, my algorithm assigns 1 to m[i][j]
, for some i = 0, 1, ..., N
, where N
is the size of the set S
, and for some j = 0, 1, ... , M
, where M
is the number we want to obtain, when either the current number in the subset, that is S[i - 1]
, is equal to the number we want to obtain M_j
, or when the previous solution to the subproblem, where the number we want to obtain is M_j - S[i - j]
, was 1.
That might seem a confusing explanation, and I think the code is self-explanatory.
Is my algorithm correct for all instances of the problem?
Is there a way I can improve it?
subset
ands
. \$\endgroup\$