2016-10-19 3 views
0

Я работал над основной проблемой суммы подмножества. Учитывая сумму, скажем, 6, и числа [1,2,3,4,5,6]), мне пришлось найти общее количество комбинаций, которые составили s (для s = 6: [1,5], [2,4], [1,2,3]).Получение комбинаций из memoized алгоритма подмножества сумм?

Я смог решить эту проблему с помощью грубой силы, не смог найти способ ее мемуаровать, поэтому мой код неработоспособный при достаточно больших значениях n.

Я нашел memoized алгоритм here, который работает достаточно хорошо, но он дает мне только количество комбинаций (так что для s = 6 количество комбинаций будет 3) - не сами комбинации. Можно ли как мемуазировать эту проблему (чтобы я мог запускать ее для очень больших значений s) и могли сами выводить сами комбинации?

+1

Этот рекурсивный алгоритм создает дерево всех возможных решений, начиная с общей и вычитая значения, и только возвращение '1' (складывает все ветви), если он вычитает точно в общую сумму (т.е. заканчивается на '0'). Для больших чисел это может затруднить выполнение стандартной глубины рекурсии pythons. – AChampion

ответ

0

Вы можете упростить проблему, используя itertools.combinations() как:

>>> from itertools import combinations 
>>> s = 6 
>>> my_list = range(1, s) 
# Value of 'my_list': 
# [1, 2, 3, 4, 5] 

>>> my_combinations = [combinations(my_list, i) for i in range(2, s)] 
# Value of 'my_combinations' (in actual will be containg <combinations> objects): 
# [[(1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5), (3, 4), (3, 5), (4, 5)], [(1, 2, 3), (1, 2, 4), (1, 2, 5), (1, 3, 4), (1, 3, 5), (1, 4, 5), (2, 3, 4), (2, 3, 5), (2, 4, 5), (3, 4, 5)], [(1, 2, 3, 4), (1, 2, 3, 5), (1, 2, 4, 5), (1, 3, 4, 5), (2, 3, 4, 5)], [(1, 2, 3, 4, 5)]] 

>>> my_required_set = [my_set for my_sublist in my_combinations for my_set in my_sublist if sum(my_set) == s] 
>>> my_required_set 
[(1, 5), (2, 4), (1, 2, 3)] 
+0

Не используйте 'list()' wrapping в определении 'my_combinations'; он бесполезно реализует все комбинации комбинаций в памяти, когда вам нужно только повторять их один раз, по одному в любом случае. Для небольших входов это не страшно, но комбинации имеют большой-O, основанный на факториале ввода, и даже немного большие входы могут использовать всю вашу оперативную память. Опущение «списка» означает, что вам нужно потратить только процессор, а не память, на обработку отклоненных элементов. – ShadowRanger

+0

@ShadowRanger: Действительная точка. Обновлен ответ –

+0

Спасибо за ответ. К сожалению, он не предлагает memoization - я только что отредактировал свой оригинальный вопрос, чтобы попытаться сделать это требование более ясным, поскольку это было не очевидно изначально. – rumdrums

Смежные вопросы