pythonalgorithmdata-structuresdynamic-programmingsubset-sum

Getting all subsets from subset sum problem on Python using Dynamic Programming


I am trying to extract all subsets from a list of elements which add up to a certain value.

Example -

Have tried different approaches and getting the expected output but on a huge list of elements it is taking a significant amount of time. Can this be optimized using Dynamic Programming or any other technique.

Approach-1

def subset(array, num):
    result = []
    def find(arr, num, path=()):
        if not arr:
            return
        if arr[0] == num:
            result.append(path + (arr[0],))
        else:
            find(arr[1:], num - arr[0], path + (arr[0],))
            find(arr[1:], num, path)
    find(array, num)
    return result

numbers = [2, 2, 1, 12, 15, 2, 3]
x = 7
subset(numbers,x)

Approach-2

def isSubsetSum(arr, subset, N, subsetSize, subsetSum, index , sum):
    global flag
    if (subsetSum == sum):
        flag = 1
        for i in range(0, subsetSize):
            print(subset[i], end = " ")
        print("")
    else:
        for i in range(index, N):
            subset[subsetSize] = arr[i]
            isSubsetSum(arr, subset, N, subsetSize + 1, 
                        subsetSum + arr[i], i + 1, sum)

Solution

  • Here is the optimized solution to the problem with a complexity of O(n^2).

    def get_subsets(data: list, target: int):
    # initialize final result which is a list of all subsets summing up to target
    subsets = []
    
    # records the difference between the target value and a group of numbers
    differences = {}
    
    for number in data:
        prospects = []
    
        # iterate through every record in differences
        for diff in differences:
    
            # the number complements a record in differences, i.e. a desired subset is found
            if number - diff == 0:
                new_subset = [number] + differences[diff]
                new_subset.sort()
                if new_subset not in subsets:
                    subsets.append(new_subset)
    
            # the number fell short to reach the target; add to prospect instead
            elif number - diff < 0:
                prospects.append((number, diff))
    
        # update the differences record
        for prospect in prospects:
            new_diff = target - sum(differences[prospect[1]]) - prospect[0]
            differences[new_diff] = differences[prospect[1]] + [prospect[0]]
        differences[target - number] = [number]
    
    return subsets