本文涉及知识点
离线查询 堆
LeetCode2503. 矩阵查询可获得的最大分数
给你一个大小为 m x n 的整数矩阵 grid 和一个大小为 k 的数组 queries 。
找出一个大小为 k 的数组 answer ,且满足对于每个整数 queries[i] ,你从矩阵 左上角 单元格开始,重复以下过程:
如果 queries[i] 严格 大于你当前所处位置单元格,如果该单元格是第一次访问,则获得 1 分,并且你可以移动到所有 4 个方向(上、下、左、右)上任一 相邻 单元格。
否则,你不能获得任何分,并且结束这一过程。
在过程结束后,answer[i] 是你可以获得的最大分数。注意,对于每个查询,你可以访问同一个单元格 多次 。
返回结果数组 answer 。
示例 1:
输入:grid = [[1,2,3],[2,5,7],[3,5,1]], queries = [5,6,2]
输出:[5,8,1]
解释:上图展示了每个查询中访问并获得分数的单元格。
示例 2:
输入:grid = [[5,2,1],[1,1,2]], queries = [3]
输出:[0]
解释:无法获得分数,因为左上角单元格的值大于等于 3 。
提示:
m == grid.length
n == grid[i].length
2 <= m, n <= 1000
4 <= m * n <= 105
k == queries.length
1 <= k <= 104
1 <= grid[i][j], queries[i] <= 106
离线查询
对 queries按升序排序,并从小到大处理que。
ret记录所有能访问的单格的数量。
小根堆neiBo 记录所有和能访问的单格相邻的单格信息。包括:值、行、列
如果堆顶元素的值小于que
ret++
相邻的元素加到neiBo。
注意: 类似于BFS,每个单格只入堆一次。
代码
核心代码
class Solution {
public:
vector<int> maxPoints(vector<vector<int>>& grid, vector<int>& queries) {
const int R = grid.size(), C = grid[0].size();
vector<int> indexs(queries.size());
iota(indexs.begin(), indexs.end(),0);
sort(indexs.begin(), indexs.end(), [&](int i1, int i2) {return queries[i1] < queries[i2]; });
priority_queue<tuple<int, int, int>, vector<tuple<int, int, int>>, greater<>> heap;
vector<vector<bool>> vis(R, vector<bool>(C));
auto Add = [&](int r, int c) {
if (vis[r][c]) { return; }
heap.emplace(make_tuple(grid[r][c], r, c));
vis[r][c] = true;
};
Add(0, 0);
int ret = 0;
vector<int> vRet(queries.size());
for (int i : indexs) {
while (heap.size() && (get<0>(heap.top()) < queries[i])) {
ret++;
auto [val, r, c] = heap.top();
heap.pop();
if (r + 1 < R) {
Add(r + 1, c);
}
if (r >0) {
Add(r - 1, c);
}
if (c + 1 < C) {
Add(r, c + 1);
}
if (c > 0) {
Add(r, c - 1);
}
}
vRet[i] = ret;
}
return vRet;
}
};
单元测试
template<class T1, class T2>
void AssertEx(const T1& t1, const T2& t2)
{
Assert::AreEqual(t1, t2);
}
template<class T>
void AssertEx(const vector<T>& v1, const vector<T>& v2)
{
Assert::AreEqual(v1.size(), v2.size());
for (int i = 0; i < v1.size(); i++)
{
Assert::AreEqual(v1[i], v2[i]);
}
}
template<class T>
void AssertV2(vector<vector<T>> vv1, vector<vector<T>> vv2)
{
sort(vv1.begin(), vv1.end());
sort(vv2.begin(), vv2.end());
Assert::AreEqual(vv1.size(), vv2.size());
for (int i = 0; i < vv1.size(); i++)
{
AssertEx(vv1[i], vv2[i]);
}
}
namespace UnitTest
{
vector<vector<int>> grid;
vector<int> queries;
TEST_CLASS(UnitTest)
{
public:
TEST_METHOD(TestMethod001)
{
grid = { {1,2,3},{2,5,7},{3,5,1} }, queries = { 5 };
auto res = Solution().maxPoints(grid, queries);
AssertEx(vector<int>{5,}, res);
}
TEST_METHOD(TestMethod00)
{
grid = { {1,2,3},{2,5,7},{3,5,1} }, queries = { 5,6,2 };
auto res = Solution().maxPoints(grid, queries);
AssertEx(vector<int>{5, 8, 1}, res);
}
TEST_METHOD(TestMethod01)
{
grid = { {5,2,1},{1,1,2} }, queries = { 3 };
auto res = Solution().maxPoints(grid, queries);
AssertEx(vector<int>{0}, res);
}
};
}
扩展阅读
视频课程
先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771
如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176
相关推荐
我想对大家说的话 |
---|
《喜缺全书算法册》以原理、正确性证明、总结为主。 |
按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。 |
有效学习:明确的目标 及时的反馈 拉伸区(难度合适) 专注 |
闻缺陷则喜(喜缺)是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。 |
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。 |
如果程序是一条龙,那算法就是他的是睛 |
测试环境
操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。