Мне нужен эффективный способ просмотреть список наборов ints
, чтобы увидеть, что любые два набора имеют одинаковую сумму. В частности, в этом случае я генерирую силовую схему списка ints, которые приводятся в качестве аргумента. Из этого набора полномочий мне нужно найти пару подмножеств, которые суммируются с одним и тем же значением.Что такое быстрый способ найти два набора с равными суммами в C++?
В настоящее время я пытаюсь использовать динамический программный подход (объяснение ниже):
typedef std::vector<int> intvec;
typedef std::vector<std::vector<int> > intvecvec;
typedef std::multimap<int,int> intmap;
/* Functions previously shown here that were removed:
* intvecvec search_for_sum(intvec num_list)
* and
* int sum_exists(std::vector<intvec> pset, int index, intmap &sums)
*/
/* This function was previously just called powerset(), and wasn't
* shown because the problem wasn't happening here. After refactoring,
* I removed the functions that were shown here previously and simply
* iteratively checked for sum matches while generating the powerset
*/
intvecvec powerset_search(intvec num_list)
{
intvecvec result;
std::multimap<int, intvec> power_set;
for (int c = 0; c < pow(2, num_list.size()); c++) {
intvec temp;
for (int i = 0; i < num_list.size(); i++) {
if (c & (1 << i)) {
temp.push_back(num_list.at(i));
}
}
int sum = std::accumulate(temp.begin(), temp.end(), 0);
std::multimap<int, intvec>::iterator it = power_set.find(sum);
if (it == power_set.end()) {
power_set.insert(std::make_pair(sum, temp));
} else {
result.push_back(it->second);
result.push_back(temp);
break;
}
}
return result;
}
search_for_sum()
создает Powerset данного списка ints
, наряду с multimap
называемых сумм. Для каждого элемента в силовом наборе вычисляется его сумма. Если эта сумма еще не встречена, сумма и текущий индекс вставляются в sums
. В противном случае возвращается текущий набор и тот, который уже был вставлен в sums
.
Это работает. Проблема в том, что для больших размеров num_list
это может занять несколько минут, если вы найдете решение. Это значительно медленнее, чем метод грубой силы, просто делающий двойной for
-loop и вычисляющий суммы каждый раз, чтобы найти совпадение. Есть ли лучший способ для меня сделать это?
EDIT: Так что я был в состоянии решить эту проблему, перемещая мою сумму проверки шаг до того, когда Powerset фактически генерируется, итеративно проверяя все ранее введенные суммы и возвращение, если совпадение найдено. Но, как было предложено в комментариях, я также переделал описание проблемы (надеюсь) устранить ту неопределенность, которая была там первоначально.
«В частности, в этом случае я просматриваю силовую схему некоторой заданной последовательности целых чисел, но теоретически это будет работать для любого списка множеств». Я думаю, что * но * неуместен. «Список наборов» подразумевает некоторый разумно короткий список произвольных множеств, в то время как набор полномочий очень неоправданно большой, как правило, и ограничен исходным набором. Так что это звучит как проблема X/Y, что для вашей исходной проблемы X вы решили, что решение Y с poweret должно обязательно быть The Thing, но, эй, оказалось, что оно медленное, как меласса, поэтому давайте спросим об этом на SO , Лучше спросите об оригинале X. –
Если я не понял проблему, создайте два массива сумм, отсортируйте их, а затем один проход скажет вам, какие из них совпадают. – Mike
Можете ли вы перефразировать исходную проблему с самого начала? Теперь есть двусмысленность, и это не ясно. Также у вас есть мертвый код типа 'intsetvec', который не помогает. –