合并k个排序的向量

时间:2019-10-08 10:37:19

标签: c++ merge

这可能是其他问题的重复,但是我没有找到任何解决方案。 这是我使用堆合并k个排序列表的实现,该堆在第一个和最后一个+ 1个元素上存储迭代器,然后提取最小值,如果需要,请移动迭代器并更新状态。

一些约束:每个数组的长度小于10 * k,所有元素小于100。

这是为面试准备而完成的,因此请耐心等待代码风格,不良的生产实践等。解决方案没有通过一些测试,我无法显示,但是最终它会出现运行时错误。

using int_iterator = typename vector<int>::const_iterator;
using int_range = pair<int_iterator, int_iterator>;

struct comp
{
    bool operator()(const int_range& a, const int_range& b) const
    {
        return *a.first >= *b.first;
    }
};

vector<int> merge_k(const vector<vector<int>>& arrays)
{
    priority_queue<int_range, vector<int_range>, comp> q;

    for(auto& arr: arrays)
    {
        q.push(make_pair(arr.begin(), arr.end()));
    }

    vector<int> result;

    while(!q.empty())
    {
        auto it = q.top();
        result.push_back(*it.first);
        q.pop();

        if(it.first + 1 != it.second)
        {
            ++it.first;
            q.push(make_pair(it.first, it.second));
        }

    }

    return result;
}

1 个答案:

答案 0 :(得分:0)

正如已经在注释中指出的那样,您的代码中存在两个问题:

首先,std::priority_queue需要严格的弱排序(就像std::setstd::map之类的其他已排序容器一样,请参见Compare template parameter上的注释),换句话说,元素不能与自己比较。所以你需要更换

return *a.first >= *b.first;
//              ^^

使用

return *a.first > *b.first;
//              ^

第二,您不考虑空向量-除非任务明确将其排除,否则您需要这样做:

for(auto& arr: arrays)
{
    if(!arr.empty()) { /*...*/ }
}

否则,*it.first将取消引用结束迭代器,it.first + 1将其递增。

优化机会:避免在目标向量内重新分配:

size_t totalSize = 0;
for(auto& arr: arrays)
{
    if(!arr.empty())
    {
        totalSize += arr.size();
        /*...*/
    }
}
result.reserve(totalSize);