Число различных сумм подмножеств

У меня есть набор N, для N > 3, различных целых чисел, и задача состоит в том, чтобы найти все различные суммы 3-подмножеств данного множества. 3-подмножество - подмножество, мощность которого равна 3.

Я знаю, что глупым способом будет делать кубический поиск по всем возможным суммам, а затем разобрать все дубликаты. Есть ли более эффективный способ сделать это? Я программирую на C.

EDIT: мне хотелось узнать более общий алгоритм, если бы количество элементов было увеличено.

Ответ 1

Используя динамическое программирование, вы можете найти количество различных сумм в O(n*MAX), где MAX - максимальное значение в массиве.

Посмотрим на рекурсивную функцию:

f(W,n,i) = f(W,n-1,i) OR (i != 0 ? f(W-item(n),n-1,i-1) : false)
f(0,0,0) = true
f(W,n,0) = false (W != 0)
f(W,0,i) = false (W != 0)
f(W,n,i) = false (W < 0)
(I have a feeling I forgot another failing base clause, so make sure if I didn't)

Теперь, если вы создадите этот снизу вверх с помощью динамического программирования, до W=3*MAX, ваш ответ будет в основном числом разных W, которые для них f(W,n,3) == true.

Построение таблицы будет O(MAX*3 * n * 3) = O(MAX*n), этап пост-обработки подсчета количества различных W, дающих желаемую сумму, составляет O(MAX), поэтому решение остается O(MAX * n)

Ответ 2

Если вы подозреваете, что у вас может быть много дублированных сумм, вы можете сначала вычислить все отдельные суммы с двумя подмножествами, а для каждой отдельной суммы в 2 поднабора, которую вы найдете, отслеживайте, какую пару вы нашли, что дало вам сумма. Если все ваши цифры различны, то если вы когда-либо найдете другую пару, которая дает вам ту же сумму, вы должны пометить сумму как "несколько", и вы можете удалить пару, которую вы храните для нее, если хотите. Теперь у вас есть набор из двух подмножеств, и каждая сумма либо имеет одну пару, хранящуюся вместе с ней, либо помечена как "кратная". Для каждой суммы с двумя подмножествами, если она помечена как "множественная", вы перебираете все числа в вашем исходном наборе и записываете все суммы из трех подмножеств, которые вы можете сформировать, добавив каждый номер к вашей сумме в 2 поднабора. В противном случае, если сумма в 2 поднабора не помечена как "кратная", и у вас есть пара (a, b), связанная с ней, то вы делаете то же самое, кроме пропусков a и b, когда вы выполняете итерирование через ваш исходный набор чисел, Вот как вы получаете все четные суммы из 3 подмножеств. Если у вас есть n чисел, и они делают N отличных сумм из двух подмножеств, то сложность этого подхода - O (nN), если вы используете хеш-таблицы для обнаружения дубликатов на двух этапах алгоритма, которые могут быть намного лучше, чем грубые сила O (n ^ 3 log n), особенно если у вас довольно плотное множество целых чисел.