2146. 价格范围内最高排名的 K 样物品
给你一个下标从 0 开始的二维整数数组 grid
,它的大小为 m x n
,表示一个商店中物品的分布图。数组中的整数含义为:
0
表示无法穿越的一堵墙。1
表示可以自由通过的一个空格子。从一个格子走到上下左右相邻格子花费 1
步。
同时给你一个整数数组 pricing
和 start
,其中 pricing = [low, high]
且 start = [row, col]
,表示你开始位置为 (row, col)
,同时你只对物品价格在 闭区间 [low, high]
之内的物品感兴趣。同时给你一个整数 k
。
你想知道给定范围 内 且 排名最高 的 k
件物品的 位置 。排名按照优先级从高到低的以下规则制定:
start
到一件物品的最短路径需要的步数(较近 距离的排名更高)。请你返回给定价格内排名最高的 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 == grid.length
n == grid[i].length
1 <= m, n <= 105
1 <= m * n <= 105
0 <= grid[i][j] <= 105
pricing.length == 2
2 <= low <= high <= 105
start.length == 2
0 <= row <= m - 1
0 <= col <= n - 1
grid[row][col] > 0
1 <= k <= m * n
原站题解
golang 解法, 执行用时: 444 ms, 内存消耗: 19.2 MB, 提交时间: 2023-10-10 16:04:31
var dirs = []struct{ x, y int }{{-1, 0}, {1, 0}, {0, -1}, {0, 1}} func highestRankedKItems(grid [][]int, pricing, start []int, k int) (ans [][]int) { m, n := len(grid), len(grid[0]) low, high := pricing[0], pricing[1] sx, sy := start[0], start[1] vis := make([][]bool, m) for i := range vis { vis[i] = make([]bool, n) } vis[sx][sy] = true q := [][]int{{sx, sy}} for len(q) > 0 { // 分层 BFS // 此时 q 内所有元素到起点的距离均相同,因此按照题目中的第 2~4 关键字排序后,就可以将价格在 [low,high] 内的位置加入答案 sort.Slice(q, func(i, j int) bool { ax, ay, bx, by := q[i][0], q[i][1], q[j][0], q[j][1] pa, pb := grid[ax][ay], grid[bx][by] return pa < pb || pa == pb && (ax < bx || ax == bx && ay < by) }) l := sort.Search(len(q), func(i int) bool { return grid[q[i][0]][q[i][1]] >= low }) r := sort.Search(len(q), func(i int) bool { return grid[q[i][0]][q[i][1]] > high }) ans = append(ans, q[l:r]...) if len(ans) >= k { return ans[:k] } tmp := q q = nil for _, p := range tmp { for _, d := range dirs { if x, y := p[0]+d.x, p[1]+d.y; 0 <= x && x < m && 0 <= y && y < n && !vis[x][y] && grid[x][y] != 0 { vis[x][y] = true q = append(q, []int{x, y}) } } } } return }
cpp 解法, 执行用时: 564 ms, 内存消耗: 161.7 MB, 提交时间: 2023-10-10 16:04:19
int dirs[4][2] = {{-1, 0}, {1, 0}, {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 m = grid.size(), n = grid[0].size(); int low = pricing[0], high = pricing[1]; int sx = start[0], sy = start[1]; bool vis[m][n]; memset(vis, 0, sizeof(vis)); vis[sx][sy] = true; vector<pair<int, int>> q = {{sx, sy}}; while (!q.empty()) { // 分层 BFS // 此时 q 内所有元素到起点的距离均相同,因此按照题目中的第 2~4 关键字排序后,就可以将价格在 [low,high] 内的位置加入答案 sort(q.begin(), q.end(), [&](auto &a, auto &b) { int pa = grid[a.first][a.second], pb = grid[b.first][b.second]; return pa < pb || pa == pb && a < b; }); for (auto &p: q) { int g = grid[p.first][p.second]; if (low <= g && g <= high) { ans.push_back({p.first, p.second}); if (ans.size() == k) return ans; } } vector<pair<int, int>> qq; for (auto &p: q) for (auto &d: dirs) { int x = p.first + d[0], y = p.second + d[1]; if (0 <= x && x < m && 0 <= y && y < n && !vis[x][y] && grid[x][y]) { vis[x][y] = true; qq.emplace_back(x, y); } } q = move(qq); } return ans; } };
java 解法, 执行用时: 102 ms, 内存消耗: 72.5 MB, 提交时间: 2023-10-10 16:04:02
class Solution { static final int[][] dirs = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; public List<List<Integer>> highestRankedKItems(int[][] grid, int[] pricing, int[] start, int k) { var ans = new ArrayList<List<Integer>>(); int m = grid.length, n = grid[0].length; var vis = new boolean[m][n]; vis[start[0]][start[1]] = true; var q = new ArrayList<int[]>(); q.add(start); while (!q.isEmpty()) { // 分层 BFS // 此时 q 内所有元素到起点的距离均相同,因此按照题目中的第 2~4 关键字排序后,就可以将价格在 [low,high] 内的位置加入答案 q.sort((a, b) -> { int pa = grid[a[0]][a[1]], pb = grid[b[0]][b[1]]; return pa != pb ? pa - pb : a[0] != b[0] ? a[0] - b[0] : a[1] - b[1]; }); for (var p : q) if (pricing[0] <= grid[p[0]][p[1]] && grid[p[0]][p[1]] <= pricing[1]) { ans.add(List.of(p[0], p[1])); if (ans.size() == k) return ans; } var tmp = q; q = new ArrayList<>(); for (var p : tmp) for (var d : dirs) { int x = p[0] + d[0], y = p[1] + d[1]; if (0 <= x && x < m && 0 <= y && y < n && !vis[x][y] && grid[x][y] > 0) { vis[x][y] = true; q.add(new int[]{x, y}); } } } return ans; } }
cpp 解法, 执行用时: 548 ms, 内存消耗: 165.5 MB, 提交时间: 2023-10-10 16:03:22
class Solution { private: static constexpr int dx[4] = {1, 0, -1, 0}; static constexpr int dy[4] = {0, 1, 0, -1}; public: vector<vector<int>> highestRankedKItems(vector<vector<int>>& grid, vector<int>& pricing, vector<int>& start, int k) { vector<tuple<int, int, int, int>> items; // 感兴趣物品的信息 queue<tuple<int, int, int>> q; // 广度优先搜索队列 q.emplace(start[0], start[1], 0); if (pricing[0] <= grid[start[0]][start[1]] && grid[start[0]][start[1]] <= pricing[1]) { items.emplace_back(0, grid[start[0]][start[1]], start[0], start[1]); } grid[start[0]][start[1]] = 0; // 避免重复遍历 int m = grid.size(); int n = grid[0].size(); while (!q.empty()) { auto [x, y, d] = q.front(); q.pop(); for (int i = 0; i < 4; ++i) { // 遍历相邻坐标,并进行对应操作 int nx = x + dx[i]; int ny = y + dy[i]; if (nx >= 0 && nx < m && ny >= 0 && ny < n && grid[nx][ny] > 0) { if (pricing[0] <= grid[nx][ny] && grid[nx][ny] <= pricing[1]) { items.emplace_back(d + 1, grid[nx][ny], nx, ny); } q.emplace(nx, ny, d + 1); grid[nx][ny] = 0; // 避免重复遍历 } } } sort(items.begin(), items.end()); // 按照优先级从高到低排序 vector<vector<int>> res; // 排名最高 k 件物品的坐标 int cnt = min(k, static_cast<int>(items.size())); for (int i = 0; i < cnt; ++i) { auto [d, price, x, y] = items[i]; res.push_back({x, y}); } return res; } };
python3 解法, 执行用时: 900 ms, 内存消耗: 57.1 MB, 提交时间: 2023-10-10 16:03:03
class Solution: def highestRankedKItems(self, grid: List[List[int]], pricing: List[int], start: List[int], k: int) -> List[List[int]]: items = [] # 感兴趣物品的信息 q = deque([(start[0], start[1], 0)]) # 广度优先搜索队列 if pricing[0] <= grid[start[0]][start[1]] <= pricing[1]: items.append([0, grid[start[0]][start[1]], start[0], start[1]]) grid[start[0]][start[1]] = 0 # 避免重复遍历 m = len(grid) n = len(grid[0]) dx = [1, 0, -1, 0] dy = [0, 1, 0, -1] while q: x, y, d = q.popleft() for i in range(4): # 遍历相邻坐标,并进行对应操作 nx, ny = x + dx[i], y + dy[i] if 0 <= nx < m and 0 <= ny < n and grid[nx][ny] > 0: q.append((nx, ny, d + 1)) if pricing[0] <= grid[nx][ny] <= pricing[1]: items.append([d + 1, grid[nx][ny], nx, ny]) grid[nx][ny] = 0 # 避免重复遍历 items.sort() # 按照优先级从高到低排序 res = [item[2:] for item in items][:k] # 排名最高 k 件物品的坐标 return res
python3 解法, 执行用时: 1636 ms, 内存消耗: 51.9 MB, 提交时间: 2023-10-10 16:02:47
class Solution: def highestRankedKItems(self, grid: List[List[int]], pricing: List[int], start: List[int], k: int) -> List[List[int]]: ans = [] m, n = len(grid), len(grid[0]) low, high = pricing sx, sy = start vis = {(sx, sy)} q = [(sx, sy)] while q: # 分层 BFS # 此时 q 内所有元素到起点的距离均相同,因此按照题目中的第 2~4 关键字排序后,就可以将价格在 [low,high] 内的位置加入答案 q.sort(key=lambda p: (grid[p[0]][p[1]], p)) ans.extend(p for p in q if low <= grid[p[0]][p[1]] <= high) if len(ans) >= k: return ans[:k] tmp = q q = [] for i, j in tmp: for x, y in (i, j - 1), (i, j + 1), (i - 1, j), (i + 1, j): if 0 <= x < m and 0 <= y < n and grid[x][y] and (x, y) not in vis: vis.add((x, y)) q.append((x, y)) return ans