Python: Recursive Function. How to return all subsets of targetsum

梦想与她 提交于 2021-01-01 06:45:36

问题


My code is not showing the shortest subset eg [7] or it is not reading all the subsets, [7], [3,4] to return the shortest subset. Can explain why only 1 set of result is return and how should I modify it to show all subset? Thanks

Image of Code that i wanted to follow as below


def howsum(targetsum,numbers,combo=None):
    
    if combo == None:
        combo = list()
    if targetsum == 0: return [ ]
    if targetsum < 0: return None
    shortcombo = None
    
    for number in numbers:
        remainder = targetsum - number      
        
        combo = howsum(remainder,numbers,combo)
        if combo != None:
            combo.append(number)
            if shortcombo == None or len(shortcombo) > len(combo):
                shortcombo = combo
                return shortcombo
                                    
    return shortcombo
     
print(howsum(7,[4,3,7]))

回答1:


Wrote code that closely matches the original JavaScript.

Although JavaScript names will work, I refactored function and variable names to agree with Python style, namely:

  • Function names should be lowercase, with words separated by underscores as necessary to improve readability.
  • Variable names follow the same convention as function names.

Code

def best_sum(target_sum, numbers):
    if target_sum == 0: return []
    if target_sum < 0: return None
    
    shortest_combination = None

    for num in numbers:
        remainder = target_sum - num
        remainder_combination = best_sum(remainder, numbers)
        if remainder_combination != None:
            combination = [*remainder_combination, num] # Python * equivalent to JavaSscript ...
            if shortest_combination == None or len(combination) < len(shortest_combination):
                shortest_combination = combination
    
    return shortest_combination

Test

print(bestSum(7, [3, 4, 7])) # Output: [7]

Using Memoization (i.e. caching)

def best_sum(target_sum, numbers, memo = None):
    if memo is None:
        memo = {0:[]}
    if target_sum < 0:
        return None
    if target_sum in memo:
        return memo[target_sum]

    shortest_combination = None

    for num in numbers:
        remainder = target_sum - num

        remainder_combination = best_sum(remainder, numbers, memo)
        if remainder_combination != None:
            combination = [*remainder_combination, num] # Python * equivalent to JavaSscript ...
            if shortest_combination == None or len(combination) < len(shortest_combination):
                shortest_combination = combination

    memo[target_sum] = shortest_combination

    return memo[target_sum]

print(best_sum(7, [3, 4, 7]))  # Output: 7
# Following very slow on non-memoized version
print(best_sum(100,[10,1,25])) # Output: [25, 25, 25, 25]



回答2:


I am not sure about this but while defining a function in python and giving 2 sets of codes it is not actually performing the second set of the code when calling out the function. I got the same problem with some other project. And I got no answers but saying I did some wrong in the code!!!




回答3:


Added memoization, however with 1 inside sets of num. the results gone haywire.

def best_sum(target_sum, numbers,memo=None):
    if memo == None:
      memo = dict()
    
    if target_sum in memo:
      return memo[target_sum]
  
    if target_sum == 0: return []
    if target_sum < 0: return None
    
    shortest_combination = None

    for num in numbers:
        remainder = target_sum - num
        remainder_combination = best_sum(remainder, numbers,memo)
        if remainder_combination != None:
            remainder_combination.append(num)
            combination = remainder_combination
            if shortest_combination == None or len(combination) < len(shortest_combination):
                shortest_combination = combination
    memo[target_sum] = shortest_combination
    return shortest_combination

print(best_sum(100,[5,1,25]))

This code by answer posted by DarylG works. By changing the .append to [*list,var] However I dont understand why is the result different between function append and *

def best_sum(target_sum, numbers,memo=None):
    if memo == None:
      memo = dict()
    
    if target_sum in memo:
      return memo[target_sum]
  
    if target_sum == 0: return []
    if target_sum < 0: return None
    
    shortest_combination = None

    for num in numbers:
        remainder = target_sum - num
        remainder_combination = best_sum(remainder, numbers,memo)
        if remainder_combination != None:
            combination = [*remainder_combination,num] #this line from append to *
            if shortest_combination == None or len(combination) < len(shortest_combination):
                shortest_combination = combination
    memo[target_sum] = shortest_combination
    return shortest_combination

print(best_sum(100,[5,1,25]))



回答4:


I checked out your code. What I felt missing was

  • Incorrect placement of return and storing the values inside of combo (set instead of list).

     def howsum(targetsum,numbers,combo=None):
     if combo == None:
         combo = set()
     if targetsum == 0: 
         return [ ]
     if targetsum < 0: return None
    
     for idx,number in enumerate(numbers):
         remainder = targetsum - number
         if howsum(remainder,numbers[idx:],combo) != None:
             combo.add(number)
     else:
         return combo
     return None
    

print(howsum(7,[7,3,4,2,5]))

Hope this helps. While this gives you a solution I would recommend using a different way to solve such issues (twoSum solutions) or two pointer approach with O(n).



来源:https://stackoverflow.com/questions/65386932/python-recursive-function-how-to-return-all-subsets-of-targetsum

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!