Сортировка комбинаций по сумме его элементов в 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). Надеюсь, это поможет!