从m个数组的元素组合中提取n个最低和,用于巨大的数据集

时间:2014-09-22 12:01:40

标签: c++ arrays algorithm sorting ranking

假设您有许多包含整数的未排序数组。你的工作是做出数组的总和。总和必须包含每个数组中的一个值,即(对于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表示法)?

1 个答案:

答案 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);
    }
}