LeetCode 2353. 设计食物评分系统 维护哈希表+set

5 篇文章 0 订阅

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

修改 系统中列出的某种食物的评分。
返回系统中某一类烹饪方式下评分最高的食物。
实现 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 是 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 * 104
n == foods.length == cuisines.length == ratings.length
1 <= foods[i].length, cuisines[i].length <= 10
foods[i]、cuisines[i] 由小写英文字母组成
1 <= ratings[i] <= 108
foods 中的所有字符串 互不相同
在对 changeRating 的所有调用中,food 是系统中食物的名字。
在对 highestRated 的所有调用中,cuisine 是系统中 至少一种 食物的烹饪方式。
最多调用 changeRating 和 highestRated 总计 2 * 104 次

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/design-a-food-rating-system
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

class FoodRatings {
public:
    /*
        一种食物对应一种烹饪方式和一个评分
        食物不重复,烹饪方式只有几种
        要求支持修改食物的评分   支持取得指定烹饪方式下的评分最高的食物名称

        那么对于每种烹饪方式,维护一个对应他的集合set, set是平衡树,查询时间是O(n)级别
        set中存评分和食物名称
        set会自动按照所存元素的小于号来比较,而pair是自带一个小于号的

        修改食物评分,这个会影响每种烹饪方式对应的最高评分
        一种食物 -> 一个评分
        一种食物 -> 一种烹饪方式

        所以总共维护三个:
        一种烹饪方式 -> 一个食物和评分的集合(这个集合支持查找最高评分对应的食物) 
    */


        // 烹饪方式 -> 选用此烹饪方式的集合,集合中的元素是一个
        // pair<int, string> 评分和食物名称,因为题中要求返回评分最高的食物名字
        // 如果存在并列,则返回字典序较小的名字,pair排序先看第一位,默认从小到大
        // 排序,所以第一位是评分,第二位是食物名称。 
        unordered_map<string, set<pair<int, string>>> hash;    
        // 一种食物 -> 一种烹饪方式
        unordered_map<string, string> c;
        // 一种食物 -> 一个评分
        unordered_map<string, int> r;

    FoodRatings(vector<string>& foods, vector<string>& cuisines, vector<int>& ratings) {
    
        for(int i = 0; i < foods.size(); i ++){
            c[foods[i]] = cuisines[i];
            r[foods[i]] = ratings[i];
            // 因为hash[cuisines[i]]是一个set,所以要用insert
            // 因为pair排序默认从小到大,而我们维护的是最大的
            // 所以取个负号
            hash[cuisines[i]].insert({-ratings[i], foods[i]});
        }
    }
    
    void changeRating(string food, int newRating) {
        auto cuisine = c[food]; // 先取出food对应的食谱
        // 把原来食谱中对应的rating删掉
        hash[cuisine].erase({-r[food], food});
        r[food] = newRating;
        // 加入新的rating
        hash[cuisine].insert({-newRating, food});
    }
    
    string highestRated(string cuisine) {
        // set的头部的第二个元素
        return hash[cuisine].begin() -> second;
    }
};

/**
 * Your FoodRatings object will be instantiated and called as such:
 * FoodRatings* obj = new FoodRatings(foods, cuisines, ratings);
 * obj->changeRating(food,newRating);
 * string param_2 = obj->highestRated(cuisine);
 */
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值