这可能是其他问题的重复,但是我没有找到任何解决方案。 这是我使用堆合并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;
}
答案 0 :(得分:0)
正如已经在注释中指出的那样,您的代码中存在两个问题:
首先,std::priority_queue
需要严格的弱排序(就像std::set
或std::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);