LC.2353 | 设计食物评分系统 | 有序集合 | 负分数排序实现“最高分优先 + 字典序优先”

输入:

  • FoodRatings(foods, cuisines, ratings):初始化 n 种食物
  • changeRating(food, newRating):修改某个食物评分
  • highestRated(cuisine):查询某种烹饪方式下评分最高的食物(若并列取字典序更小)

要求:

  • 评分最高优先
  • 评分相同按字典序最小优先
  • 支持多次修改与查询

输出:

  • highestRated 返回食物名

思路:

这题核心就是维护两个维度的信息:

1)食物 -> (菜系, 当前评分)

unordered_map<string, pair<string,int>> food_info 存:

  • 方便 changeRating(food, ...) 时,O(1) 找到它属于哪个菜系 + 旧评分是多少。

2)菜系 -> 一棵有序结构,能随时拿到“最强的那个”

unordered_map<string, set<pair<int,string>>> cuisine_ratings 存:

  • 每个菜系一个 set,里面放 (-rating, food) 这样的二元组。
  • set 默认按 pair 从小到大排序:
    • -rating 越小,代表 rating 越大(最高分排最前)
    • -rating 相同,就比较 food 字符串(字典序小的排前)
  • 所以 highestRated(cuisine) 直接返回 begin()->second 即可。

changeRating 怎么做?

对一个食物:

  1. food_info 取出它的 cuisineoldRating
  2. 在对应 set 里删除旧键 (-oldRating, food)
  3. 插入新键 (-newRating, food)
  4. 更新 food_info[food].second = newRating

这样能保证每次修改后,菜系的“冠军”始终在 set.begin()


复杂度:

  • 时间复杂度:
    • 初始化:O(N log N)(每次插入 set)
    • changeRating:O(log M)(M 为该 cuisine 下食物数)
    • highestRated:O(1)(取 begin)
  • 空间复杂度:O(N)

class FoodRatings {
private:
    unordered_map<string, pair<string, int>> food_info;
    unordered_map<string, set<pair<int, string>>> cuisine_ratings;

public:
    FoodRatings(vector<string>& foods, vector<string>& cuisines, vector<int>& ratings) {
        for (int i = 0; i < (int)foods.size(); ++i) {
            food_info[foods[i]] = {cuisines[i], ratings[i]};
            cuisine_ratings[cuisines[i]].insert({-ratings[i], foods[i]});
        }
    }
    
    void changeRating(string food, int newRating) {
        auto& info = food_info[food];
        string cuisine = info.first;
        int oldRating = info.second;

        cuisine_ratings[cuisine].erase({-oldRating, food});
        cuisine_ratings[cuisine].insert({-newRating, food});

        info.second = newRating;
    }
    
    string highestRated(string cuisine) {
        return cuisine_ratings[cuisine].begin()->second;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值