Сортировка комбинаций по сумме его элементов в Python

у меня есть огромный список целых чисел в Python (1000000+ элементы), но я проиллюстрирую то, что мне нужно, примером для простоты. Предположим, у меня есть этот список:

A = [1,2,3,4,100]

Теперь я хотел бы получить все комбинации (размер 3) этого списка, поэтому я использую itertools.

combinations = itertools.combinations(A,3)

но моя проблема в том, что это вернет комбинации в лексикографическом порядке:

(1,2,3)
(1,2,4)
(1,2,100)
(1,3,4)

и так далее.

Я хотел бы получите комбинации, отсортированные по сумме его элементов. Это было бы:

(1,2,3) который суммирует 6, (1,2,4), что суммы 7, (1,3,4), который подводит 8,

и так далее.

как я могу добиться этого?

2 ответов


упорядоченные комбинации слишком велики, чтобы поместиться в памяти

количество комбинаций для 1,000,000 вещей, взятых 3 за раз, составляет 166,666,166,667,000,000. Он слишком велик, чтобы поместиться в памяти, слишком велик, чтобы его сортировать, и слишком велик, чтобы даже сделать петлю за разумное количество времени.

для того, чтобы генерировать эти комбинации лениво, см. "ГЕНЕРАЦИЯ ВСЕХ КОМБИНАЦИЙ" в брошюре Дональда Кнута о Комбинаторные Алгоритмы.

заказать комбинации, которые могут поместиться в

до тех пор, пока количество комбинаций разумно, самый прямой подход-непосредственно сортировать комбинации по их сумме:

>>> import itertools
>>> import pprint

>>> A = [1, 2, 3, 4, 100]
>>> combinations = sorted(itertools.combinations(A, 3), key=sum)
>>> pprint.pprint(combinations)
[(1, 2, 3),
 (1, 2, 4),
 (1, 3, 4),
 (2, 3, 4),
 (1, 2, 100),
 (1, 3, 100),
 (1, 4, 100),
 (2, 3, 100),
 (2, 4, 100),
 (3, 4, 100)]

методика использует sum () как ключ-функция на отсортированный().

мост между двумя мирами

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


ключ вещь, чтобы рассмотреть здесь нет.комбинаций действительно огромный ~(1000000)^^3 Таким образом, любой алгоритм сортировки с O(NlogN) будет плохим. Нам нужно что-то в O(N).

мы можем попробовать создать SortedDictionary (sorteddict) или используйте стандартную внешнюю реализацию хэша, такую как memcache, чтобы сохранить комбинацию как {sum: [tuple1, tuple2]}. Сложность для этой операции будет ~O (N)

затем создайте новый список, выполните цикл через кэш и все ценности для него. Снова сложность будет O (N).

в целом, у нас будет O(2N), который эффективнее, чем O(NLogN). Надеюсь, это поможет!