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

题目链接

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 = grid[i].length n=grid[i].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 grid[i][j] \leq 105 0≤grid[i][j]≤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 grid[row][col] > 0 grid[row][col]>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 ] ) (start[0] , start[1]) (start[0],start[1]) 到每一个位置的最短距离。

在遍历的过程中我们只记录价格 g r i d [ i ] [ j ] grid[i][j] grid[i][j] 在 [ p r i c i n g [ 0 ] , p r i c i n g [ 1 ] ] [pricing[0] , pricing[1]] [pricing[0],pricing[1]]区间的位置。

记录的形式为 {距离,价格,位置},即 { d i s t [ i ] [ j ] , g r i d [ i ] [ j ] , ( i , j ) } \{dist[i][j] , grid[i][j] , (i,j) \} {dist[i][j],grid[i][j],(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;
    }
};
相关推荐
Tisfy1 天前
LeetCode 1705.吃苹果的最大数目:贪心(优先队列) - 清晰题解
算法·leetcode·优先队列·贪心·
五月高高14 天前
Lambda表达式对List对象实现多个动态属性排序
java·排序
laufing14 天前
OD C卷【智能成绩表】
排序
闻缺陷则喜何志丹16 天前
【C++图论 BFS算法】2467. 树上最大得分和路径|2053
c++·算法·力扣·图论·bfs·路径·最大
SunnyRivers18 天前
Elasticsearch入门之HTTP高级查询操作
http·elasticsearch·排序·查询
跳跳的向阳花19 天前
16-02、JVM系列之:内存与垃圾回收篇(二)
jvm·内存··老年代·方法区·新生代
2401_858286111 个月前
102.【C语言】数据结构之用堆对数组排序
c语言·开发语言·数据结构·算法·
Just_Paranoid1 个月前
Android 中文文件名排序实现案例教程
android·排序·中文排序
极客先躯1 个月前
高级java每日一道面试题-2024年11月24日-JVM篇-说说对象分配规则?
java·jvm···对象分配规则
ahadee1 个月前
蓝桥杯每日真题 - 第20天
c语言·算法·蓝桥杯·bfs