Мой код не показывает кратчайшее подмножество, например [7], или не читает все подмножества, [7], [3,4], чтобы вернуть кратчайшее подмножество. Можете объяснить, почему возвращается только 1 набор результатов и как мне изменить его, чтобы показать все подмножество? Спасибо
Изображение кода, которому я хотел следовать, как показано ниже
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]))
[ссылка] youtu.be/oBt53YbR9Kk я пытался воспроизвести логику из этой ссылки на ютубе. Но я потерпел неудачу. Попробую почитать про отладку.
Я не уверен в этом, но при определении функции в python и предоставлении 2 наборов кодов фактически не выполняется второй набор кода при вызове функции. У меня такая же проблема с другим проектом. И я не получил ответов, кроме как сказать, что я сделал что-то не так в коде!!!
[ссылка] youtu.be/oBt53YbR9Kk я следовал коду из этого видео. Но я не могу получить тот же результат. Можете ли вы объяснить разницу?
Я проверил ваш код. Чего мне не хватало, так это
Неправильное размещение return и сохранение значений внутри комбо (set вместо списка).
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]))
Надеюсь это поможет. Хотя это дает вам решение, я бы рекомендовал использовать другой способ решения таких проблем (решения twoSum) или подход с двумя указателями с O (n).
Привет, я попробовал код, который возвращает все возможные комбинации в наборе. Могу ли я узнать, как разделить его, например, на [3,4] и [7]?. Привет также, для чисел [2,6] он должен возвращать None. Я следил за этим видео на YouTube, но не могу повторить логику. [ссылка] youtube.com/watch?v=oBt53YbR9Kk&t=7613s. В видео используется список, эквивалентный Python? или это набор.
Добавлено запоминание, однако с 1 внутри наборов num. результаты пошли наперекосяк.
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]))
Этот код по ответу, опубликованному DarylG, работает. Изменив .append
на [*list,var]
Однако я не понимаю, почему результат отличается между функцией append и *
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]))
@josephgan - Привет, Джозеф - для вашего тестового примера этот код не возвращает кратчайшее подмножество для вашего тестового примера. Он возвращает [4, 3], а не [7]. Я опубликую ответ, который точно соответствует коду JavaScript, который возвращает правильный результат.
Привет, я скучаю, написал < на сравнении len. это должно быть len(shortcombo) > len(combo). Я прочитаю ваше решение с функцией *. не знал, что это использование также. Спасибо за помощь.
@josephgan - хороший улов. Вы должны обновить свой ответ с исправлением.
Привет, Дэрри, я снова попытался реализовать мемоизацию с моим кодом. Однако, если число содержит 1 eg (100,[10,1,25]
. С моим решением использовать append результаты пошли наперекосяк. Однако с использованием функции *. Он возвращает фактический результат. Не могли бы вы объяснить, почему? Однако без реализации мемоизации с 1 внутри числа мое решение не запуталось.
Привет Дэрил. Перепроверено. Решение для добавления не работает с огромным числом. Ничего общего с мемоизацией. Не уверен, почему.
@josephgan - я проголосовал за ваш ответ за всю проделанную вами работу. Простое исправление (которое может сказать вам, почему добавление не работает, состоит в том, чтобы вместо этого использовать: combination = remainder_combination + [num]
, что эквивалентно: combination = [*remainder_combination,num]
. Проблема заключается в добавлении и запоминании, несколько решений в кеше заметок ссылаются на один и тот же массив. Когда вы добавляете к одному, вы добавляете их ко всем combination = remainder_combination + [num]
создает отдельные массивы для решений, так что нет проблем.
Написал код, полностью соответствующий исходному JavaScript.
Хотя имена JavaScript будут работать, я провел рефакторинг имен функций и переменных, чтобы они соответствовали стилю Python, а именно:
Код
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
Тест
print(bestSum(7, [3, 4, 7])) # Output: [7]
Использование мемоизации (т. е. кэширования)
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]
Помимо использования memo/любой переменной для запоминания, вы можете использовать метод functools.lru_cache. Просто не забудьте ввести тип ввода во время тестирования.
import functools
@functools.lru_cache(maxsize=4)
def howsum(targetnum, num_list):
if targetnum == 0:
return []
if targetnum < 0:
return None
for num in num_list:
rem = targetnum - num
rem_val = howsum(rem, num_list)
if rem_val is not None:
rem_val.append(num)
return rem_val
return None
print(howsum(7, tuple([5, 3, 4, 7])))
print(howsum(8, tuple([3, 4, 2])))
print(howsum(300, tuple([7, 14])))
А вы пробовали отладку резиновых уточек? Попробуйте вручную пройтись по коду и посмотрите, придете ли вы к желаемому результату и как вы этого добьетесь. Должно быть довольно очевидно, где что-то происходит.