题目链接
Leetcode.2146 价格范围内最高排名的 K 样物品
rating : 1837
题目描述
给你一个下标从 0 0 0 开始的二维整数数组 g r i d grid grid ,它的大小为 m x n ,表示一个商店中物品的分布图。数组中的整数含义为:
0表示无法穿越的一堵墙。1表示可以自由通过的一个空格子。- 所有其他正整数表示该格子内的一样物品的价格。你可以自由经过这些格子。
从一个格子走到上下左右相邻格子花费1步。
同时给你一个整数数组 p r i c i n g pricing pricing 和 s t a r t start start ,其中 pricing = [low, high] 且 start = [row, col] ,表示你开始位置为 (row, col) ,同时你只对物品价格在 闭区间 l o w , h i g h low, high low,high 之内的物品感兴趣。同时给你一个整数 k k k 。
你想知道给定范围 内 且 排名最高 的 k k k 件物品的 位置 。排名按照优先级从高到低的以下规则制定:
- 距离:定义为从
start到一件物品的最短路径需要的步数(较近 距离的排名更高)。 - 价格:较低 价格的物品有更高优先级,但只考虑在给定范围之内的价格。
- 行坐标:较小 行坐标的有更高优先级。
- 列坐标:较小 列坐标的有更高优先级。
请你返回给定价格内排名最高的 k k k 件物品的坐标,将它们按照排名排序后返回。如果给定价格内少于 k k k 件物品,那么请将它们的坐标 全部 返回。
示例 1:

输入:grid = \[1,2,0,1,1,3,0,1,0,2,5,1], pricing = 2,5, start = 0,0, k = 3
输出:\[0,1,1,1,2,1]
解释:起点为 (0,0) 。
价格范围为 2,5 ,我们可以选择的物品坐标为 (0,1),(1,1),(2,1) 和 (2,2) 。
这些物品的排名为:
- (0,1) 距离为 1
- (1,1) 距离为 2
- (2,1) 距离为 3
- (2,2) 距离为 4 所以,给定价格范围内排名最高的 3 件物品的坐标为 (0,1),(1,1) 和 (2,1) 。
示例 2:

输入:grid = \[1,2,0,1,1,3,3,1,0,2,5,1], pricing = 2,3, start = 2,3, k = 2
输出:\[2,1,1,2]
解释:起点为 (2,3) 。
价格范围为 2,3 ,我们可以选择的物品坐标为 (0,1),(1,1),(1,2) 和 (2,1) 。
这些物品的排名为:
- (2,1) 距离为 2 ,价格为 2
- (1,2) 距离为 2 ,价格为 3
- (1,1) 距离为 3
- (0,1) 距离为 4 所以,给定价格范围内排名最高的 2 件物品的坐标为 (2,1) 和 (1,2) 。
示例 3:

输入:grid = \[1,1,1,0,0,1,2,3,4], pricing = 2,3, start = 0,0, k = 3
输出:\[2,1,2,0]
解释:起点为 (0,0) 。
价格范围为 2,3 ,我们可以选择的物品坐标为 (2,0) 和 (2,1) 。
这些物品的排名为:
- (2,1) 距离为 5
- (2,0) 距离为 6 所以,给定价格范围内排名最高的 2 件物品的坐标为 (2,1) 和 (2,0) 。 注意,k = 3 但给定价格范围内只有 2 件物品。
提示:
- m = g r i d . l e n g t h m = grid.length m=grid.length
- n = g r i d i . l e n g t h n = gridi.length n=gridi.length
- 1 ≤ m , n ≤ 1 0 5 1 \leq m, n \leq 10^5 1≤m,n≤105
- 1 ≤ m × n ≤ 105 1 \leq m \times n \leq 105 1≤m×n≤105
- 0 ≤ g r i d i j ≤ 105 0 \leq gridij \leq 105 0≤gridij≤105
- p r i c i n g . l e n g t h = 2 pricing.length = 2 pricing.length=2
- 2 ≤ l o w ≤ h i g h ≤ 105 2 \leq low \leq high \leq 105 2≤low≤high≤105
- s t a r t . l e n g t h = 2 start.length = 2 start.length=2
- 0 ≤ r o w ≤ m − 1 0 \leq row \leq m - 1 0≤row≤m−1
- 0 ≤ c o l ≤ n − 1 0 \leq col \leq n - 1 0≤col≤n−1
- g r i d r o w c o l > 0 gridrowcol > 0 gridrowcol>0
- 1 ≤ k ≤ m × n 1 \leq k \leq m \times n 1≤k≤m×n
解法:bfs + 排序
用 d i s t dist dist 记录从起点 ( s t a r t 0 , s t a r t 1 ) (start0 , start1) (start0,start1) 到每一个位置的最短距离。
在遍历的过程中我们只记录价格 g r i d i j gridij gridij 在 p r i c i n g \[ 0 , p r i c i n g 1 ] pricing\[0 , pricing1] pricing\[0,pricing1]区间的位置。
记录的形式为 {距离,价格,位置},即 { d i s t i j , g r i d i j , ( i , j ) } \{distij , gridij , (i,j) \} {distij,gridij,(i,j)}。
然后对其进行排序:
- 如果距离不一样,距离小的排在前面;
- 如果价格不一样,价格小的排在前面;
- 如果行坐标不一样,行坐标小的排在前面;
- 如果列坐标不一样,列坐标小的排在前面;
排序完之后,我们取前 k k k 个元素的位置,将其插入答案数组 a n s ans ans 即可。
时间复杂度: O ( m × n + m × n × l o g ( m × n ) ) O(m \times n + m \times n \times log(m \times n)) O(m×n+m×n×log(m×n))
C++代码:
cpp
using PII = pair<int,int>;
const int dx[4] = {1,0,-1,0};
const int dy[4] = {0,1,0,-1};
class Solution {
public:
vector<vector<int>> highestRankedKItems(vector<vector<int>>& grid, vector<int>& pricing, vector<int>& start, int k) {
vector<vector<int>> ans;
int l = pricing[0] , r = pricing[1];
int m = grid.size() , n = grid[0].size();
vector<vector<int>> dist(m,vector<int>(n,1e9));
vector<tuple<int,int,PII>> a;
queue<PII> q;
dist[start[0]][start[1]] = 0;
q.emplace(start[0],start[1]);
while(!q.empty()){
auto [x,y] = q.front();
q.pop();
int p = grid[x][y];
if(p >= l && p <= r){
auto t = make_tuple(dist[x][y],p,make_pair(x,y));
a.emplace_back(t);
}
for(int i = 0;i < 4;i++){
int nx = x + dx[i] , ny = y + dy[i];
if(nx < 0 || nx >= m || ny < 0 || ny >= n || grid[nx][ny] == 0 || dist[nx][ny] != 1e9) continue;
dist[nx][ny] = dist[x][y] + 1;
q.emplace(nx,ny);
}
}
sort(a.begin(),a.end(),[&](auto &a,auto &b){
int d1 = get<0>(a) , d2 = get<0>(b);
int p1 = get<1>(a) , p2 = get<1>(b);
int x1 = get<2>(a).first , y1 = get<2>(a).second;
int x2 = get<2>(b).first , y2 = get<2>(b).second;
if(d1 != d2) return d1 < d2;
else if(p1 != p2) return p1 < p2;
else if(x1 != x2) return x1 < x2;
else return y1 < y2;
});
int len = min((int)a.size() , k);
for(int i = 0;i < len;i++){
auto x = get<2>(a[i]).first , y = get<2>(a[i]).second;
ans.push_back({x,y});
}
return ans;
}
};