列表

详情


2146. 价格范围内最高排名的 K 样物品

给你一个下标从 0 开始的二维整数数组 grid ,它的大小为 m x n ,表示一个商店中物品的分布图。数组中的整数含义为:

从一个格子走到上下左右相邻格子花费 1 步。

同时给你一个整数数组 pricing 和 start ,其中 pricing = [low, high] 且 start = [row, col] ,表示你开始位置为 (row, col) ,同时你只对物品价格在 闭区间 [low, high] 之内的物品感兴趣。同时给你一个整数 k 。

你想知道给定范围  且 排名最高 的 k 件物品的 位置 。排名按照优先级从高到低的以下规则制定:

  1. 距离:定义为从 start 到一件物品的最短路径需要的步数(较近 距离的排名更高)。
  2. 价格:较低 价格的物品有更高优先级,但只考虑在给定范围之内的价格。
  3. 行坐标:较小 行坐标的有更高优先级。
  4. 列坐标:较小 列坐标的有更高优先级。

请你返回给定价格内排名最高的 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 件物品。

 

提示:

原站题解

去查看

上次编辑到这里,代码来自缓存 点击恢复默认模板
class Solution { public: vector<vector<int>> highestRankedKItems(vector<vector<int>>& grid, vector<int>& pricing, vector<int>& start, int k) { } };

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

上一题