假设您有许多包含整数的未排序数组。你的工作是做出数组的总和。总和必须包含每个数组中的一个值,即(对于3个数组)
sum = array1[2]+array2[12]+array3[4];
目标:您应输出生成最低总和的20种组合。
下面的解决方案是禁止的,因为算法需要能够处理10个可以包含大量整数的数组。对于大量数组,以下解决方案太慢了:
//You already have int array1, array2 and array3
int top[20];
for(int i=0; i<20; i++)
top[i] = 1e99;
int sum = 0;
for(int i=0; i<array1.size(); i++) //One for loop per array is trouble for
for(int j=0; j<array2.size(); j++) //increasing numbers of arrays
for(int k=0; k<array3.size(); k++)
{
sum = array1[i] + array2[j] + array3[k];
if (sum < top[19])
swapFunction(sum, top); //Function that adds sum to top
//and sorts top in increasing order
}
printResults(top); // Outputs top 20 lowest sums in increasing order
如何更有效地实现正确的结果(使用较低的Big O表示法)?
答案 0 :(得分:3)
通过考虑如何找到绝对最低和,以及如何找到第二低总和等,可以找到答案。
由于您最多只需要20个总和,因此您最多只需要每个数组中最低的20个值。我建议您使用std::partial_sort
。
其余部分应该能够使用priority_queue来完成,其中每个元素包含当前总和以及此总和的数组的指示。只需取每个指标索引并将其增加一,计算新总和并将其添加到优先级队列。队列中最顶层的项应始终是最低的总和之一。删除最低金额,生成下一个可能性,然后重复,直到有足够的答案。
假设所需答案的数量远小于大O应该主要是partial_sort(N + k * log(k))*数组的效率
这里有一些基本代码来演示这个想法。很有可能改善这一点。例如,我确信通过一些工作,您可以避免多次添加相同的一组指标,并且不需要执行do-while pop。
for (size_t i = 0; i < arrays.size(); i++)
{
auto b = arrays[i].begin();
partial_sort(b, b + numAnswers, arrays[i].end());
}
struct answer
{
answer(int s, vector<int> i)
: sum(s), indices(i)
{
}
int sum;
vector<int> indices;
bool operator <(const answer &o) const
{
return sum > o.sum;
}
};
auto getSum =[&arrays](const vector<int> &indices) {
auto retval = 0;
for (size_t i = 0; i < arrays.size(); i++)
{
retval += arrays[i][indices[i]];
}
return retval;
};
vector<int> initalIndices(arrays.size());
priority_queue<answer> q;
q.emplace(getSum(initalIndices), initalIndices );
for (auto i = 0; i < numAnswers; i++)
{
auto ans = q.top();
cout << ans.sum << endl;
do
{
q.pop();
} while (!q.empty() && q.top().indices == ans.indices);
for (size_t i = 0; i < ans.indices.size(); i++)
{
auto nextIndices = ans.indices;
nextIndices[i]++;
q.emplace(getSum(nextIndices), nextIndices);
}
}