Я не думаю, что использование combinations()
сработает здесь - функция возвращает комбинации массива, который вы передаете, но не создает дубликатов какого-либо данного элемента. Вы можете обойти это, используя вариант combinations_with_replacement()
, но даже в этом случае у вас будет избыток недопустимых комбинаций, и для длинных списков время выполнения станет неразрешимым.
Вместо этого рассмотрим рекурсивное решение, подобное следующему.
def reps(target, nums):
res = []
for i, v in enumerate(nums):
if target - v > 0:
res += [[v] + l for l in reps(target-v, nums[i:])]
elif target - v == 0:
res += [[v]]
return res
Здесь я беру целевую сумму и список чисел и пытаюсь вычесть каждое число из цели. Если разница точно равна 0, я добавляю это последнее значение в список. Если оно больше нуля, я продолжаю пытаться добавить элементы в список, вызывая reps()
с новым целевым значением и подмножеством исходных чисел, которое предотвращает перестановки одного и того же ответа. Я объединяю все это, добавляю предварительно выбранное значение из списка и продолжаю таким образом, пока не будет составлен список всех комбинаций.
Результат для вашего примера target=5
и nums=[1,2,3]
-
[[1, 1, 1, 1, 1], [1, 1, 1, 2], [1, 1, 3], [1, 2, 2], [2, 3]]