题目描述
方法一
从上到下遍历矩阵的所有行,假设计算出了前
代码如下:
class Solution {
public:
int kthSmallest(vector<vector<int>> &mat, int k) {
vector<int> a = {0};
for (auto &row: mat) {
vector<int> b;
for (int x: a)
for (int y: row)
b.push_back(x + y);
sort(b.begin(), b.end());
// 保留最小的 k 个
if (b.size() > k)
b.resize(k);
a = move(b);
}
return a.back();
}
};
调用std::move
函数,该函数是将一个左值转换为右值,之后便是利用移动构造函数进行拷贝,能够提高效率。
时间复杂度为 O(mnklogk)
, m
是矩阵行数,n
是列数。
方法二
其中,
将首项存入堆中之后,可以访问到它的首个元素,也就是最小的元素。此后,将该元素的下一项存入堆中。如此反复k
次,即可求得答案。通过阅读官方题解我们也可以发现,方法一的暴力法效率不高的原因在于遍历了矩阵的每一行的每一个元素
,而事实上融合优先队列,只需要k
次处理即可。
代码如下:
class Solution {
public:
int kthSmallest(vector<vector<int>>& mat, int k) {
int m = mat.size();
vector<int> prev = mat[0];
for (int i = 1; i < m; ++i)
{
//移动构造函数,提高性能
prev = move(merge(prev, mat[i], k));
}
return prev[k - 1];
}
vector<int> merge(const vector<int>& f, const vector<int>& g, int k) {
if (g.size() > f.size()) {
return merge(g, f, k);
}
priority_queue<Entry> q;
for (int i = 0; i < g.size(); ++i) {
q.emplace(0, i, f[0] + g[i]);
}
vector<int> ans;
while (k && !q.empty()) {
Entry entry = q.top();
q.pop();
ans.push_back(entry.sum);
if (entry.i + 1 < f.size())
{
q.emplace(entry.i + 1, entry.j, f[entry.i + 1] + g[entry.j]);
}
--k;
}
return ans;
}
private:
struct Entry {
int i, j, sum;
Entry(int _i, int _j, int _sum): i(_i), j(_j), sum(_sum) {}
//与sort的cmp不同,operator<为真,就把sum所在的对象排在后边
bool operator< (const Entry& that) const {
return sum > that.sum;
}
};
};
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话