题解:设计食物评分系统

https://leetcode.cn/problems/design-a-food-rating-system

- 问题描述(这部分可以直接复制)

设计一个支持下述操作的食物评分系统:

修改系统中列出的某种食物的评分。

返回系统中某一类烹饪方式下评分最高的食物。

实现 `FoodRatings` 类:

FoodRatings(String[] foods, String[] cuisines, int[] ratings)初始化系统。食物由 `foods`、`cuisines` 和 `ratings` 描述,长度均为 `n`。`foods[i]` 是第 `i` 种食物的名字。`cuisines[i]` 是第 `i` 种食物的烹饪方式。`ratings[i]` 是第 `i` 种食物的最初评分。

void changeRating(String food, int newRating)修改名字为 `food` 的食物的评分。

String highestRated(String cuisine)返回指定烹饪方式 `cuisine` 下评分最高的食物的名字。如果存在并列,返回字典序较小的名字。

注意,字符串 `x` 的字典序比字符串 `y` 更小的前提是:`x` 在字典中出现的位置在 `y` 之前,也就是说,要么 `x[i] != y[i]` 的第一个位置 `i` 处,`x[i]` 在字母表中出现的位置在 `y[i]` 之前。

示例:

输入

["FoodRatings", "highestRated", "highestRated", "changeRating", "highestRated", "changeRating", "highestRated"]

[[["kimchi", "miso", "sushi", "moussaka", "ramen", "bulgogi"], ["korean", "japanese", "japanese", "greek", "japanese", "korean"], [9, 12, 8, 15, 14, 7]], ["korean"], ["japanese"], ["sushi", 16], ["japanese"], ["ramen", 16], ["japanese"]]

输出

[null, "kimchi", "ramen", null, "sushi", null, "ramen"]

解释

FoodRatings foodRatings = new FoodRatings(["kimchi", "miso", "sushi", "moussaka", "ramen", "bulgogi"], ["korean", "japanese", "japanese", "greek", "japanese", "korean"], [9, 12, 8, 15, 14, 7]);

foodRatings.highestRated("korean"); // 返回 "kimchi"

                                   // "kimchi" 是分数最高的韩式料理,评分为 9。

foodRatings.highestRated("japanese"); // 返回 "ramen"

                                     // "ramen" 是分数最高的日式料理,评分为 14。

foodRatings.changeRating("sushi", 16); // "sushi" 现在评分变更为 16。

foodRatings.highestRated("japanese"); // 返回 "sushi"

                                     // "sushi" 是分数最高的日式料理,评分为 16。

foodRatings.changeRating("ramen", 16); // "ramen" 现在评分变更为 16。

foodRatings.highestRated("japanese"); // 返回 "ramen"

                                     // "sushi" 和 "ramen" 的评分都是 16。

                                     // 但是,"ramen" 的字典序比 "sushi" 更小。

提示:

1 <= n <= 2 * 10^4

n == foods.length == cuisines.length == ratings.length

1 <= foods[i].length, cuisines[i].length <= 10

foods[i]、cuisines[i] 由小写英文字母组成

1 <= ratings[i] <= 10^8

foods 中的所有字符串互不相同

在对 `changeRating` 的所有调用中,`food` 是系统中食物的名字。

在对 `highestRated` 的所有调用中,`cuisine` 是系统中至少一种食物的烹饪方式。

最多调用 `changeRating` 和 `highestRated` 总计 2 * 10^4 次

 - 解题思路

使用unordered_map 和 set`来存储食物评分和烹饪方式的信息,来实现了初始化系统、修改评分和返回最高评分食物的功能。

构造函数FoodRatings,在初始化系统时,遍历食物数组,将食物名称、评分和烹饪方式存储到 `fs` 和 `cs` 中。在 cs 中,使用 multiset`存储食物评分和名称的对应关系,按照评分的负值进行排序。

使用changeRating方法:根据食物名称找到对应的评分和烹饪方式,然后在对应的 multiset 中更新评分信息。首先从cs中移除旧评分信息,然后插入新的评分信息,并更新fs中的评分值。

最后使用highestRated` 方法:根据指定的烹饪方式,在对应的multiset 中找到评分最高的食物名称并返回。

 - 算法描述(应当有明确具体的步骤,可以使用代码加注释、伪代码、纯文字描述均可)

class FoodRatings {

    //记录食物名称对应的食物评分和烹饪方式

    unordered_map<string, pair<int, string>> fs;

    //记录烹饪方式对应的食物评分和食物名字集合

    unordered_map<string, set<pair<int, string>>> cs;



public:

    FoodRatings(vector<string>& foods, vector<string>& cuisines, vector<int>& ratings) {

        //for 循环遍历foods数组

        for (int i = 0; i < foods.size(); ++i) {

            //将数组中的元素foods[i]和cuisines[i]分别赋值给f和c

            auto &f = foods[i], &c = cuisines[i];

            //将评分数组ratings中的第i个元素赋值给变量r,表示当前食物的评分

            int r = ratings[i];

            //将食物f作为键,将评分r和烹饪方式c组成的pair作为值,存储到fs中

            fs[f] = {r, c};

            //将烹饪方式c作为键,将一个pair(包含-r 和 f)插入到对应键的set中

            //这里使用emplace函数,按照评分的负值进行排序

            cs[c].emplace(-r, f);

        }

    }

   

    void changeRating(string food, int newRating) {

        //从fs中根据食物名称food查找对应的评分r和烹饪方式c,

        auto &[r, c] = fs[food];//通过引用的方式,可以直接修改原始数据

        //根据烹饪方式c,从cs中获取对应的multiset s,用于存储该烹饪方式下的食物信息

        auto &s = cs[c];

        //在set s中移除评分为-r(负数表示原评分的负值)且食物为food的元素

        s.erase({-r, food});

        //向set s 中添加一个新的元素,该元素的评分为-newRating(newRating 的负值)且食物为food

        s.emplace(-newRating, food);

        //将评分r更新为新的评分newRating

        r = newRating;

    }

   

    string highestRated(string cuisine) {

        //通过查找对应烹饪方式的multiset中的第一个元素(评分最高的食物),可以快速找到评分最高的食物名称并返回

        return cs[cuisine].begin()->second;//按负值排序则begin()返回的就是最高的值

    }

};

 - 力扣提交结果

 - 分析、讨论与总结

在实现这个类的过程中,我使用了unordered_map<string, pair<int, string>> fs来存储食物名称对应的评分和烹饪方式,以及unordered_map<string, set<pair<int, string>>> cs来存储烹饪方式对应的食物评分和食物名字集合,能够快速查找和修改对应信息。

其中使用multiset存储食物评分和名称的对应关系,按照评分的负值进行排序,可以快速找到评分最高的食物,这可以使得算法更加高效。

收获是通过使用合适的数据结构和算法,可以实现高效的评分查找和更新功能。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值