1. 问题描述
2. 思路分析
由于该题不需要对键值(烹饪方式)进行排序,且需要多次访问,因此可以用一个unordered_map嵌套set来存储,其键值为烹饪方式,而实值为set,set里面存放pair(第一个元素为评分,第二给为食物名字);由于需要修改食物评分,而参数只有食物名字和想要修改的评分,而没有提供该食物原来的评分以及烹饪方式,因此我们在对第一个map更新时,就需要另外一个unordered_map来辅助,这个map的键值是食物名称,而实值为pair(第一个元素为食物评分,第二个元素为食物的烹饪方式)
注:由于题目要求“如果存在并列,返回 字典序较小 的名字”,因此我们需要对pair写一个自定义排序规则
3. 算法描述
(1)创建unordered_map<string,set<pair<int,string>,mycompare>>cm和unordered_map<string,pair<int,string>>fm
(2)在FoodRatings构造函数里面对cm和fm进行赋值
(3)在changeRating函数里,修改fm中食物的评分,并对cm进行删除和添加,进行更新
(4)在highestRated函数里,由于cm中set是按自定义排序的,所以其键值(烹饪方式)下的set的第一个元素的第二个值就是所求,返回它
4. 代码实现
class mycompare{ //谓词用于set容器对pair<int,string>作排序
public:
bool operator()(const pair<int,string>&p1,const pair<int,string>&p2)const{
if(p1.first>p2.first)return true; //先排评分
else if(p1.first==p2.first){ //评分相等时按字典序较小的排前面
if(p1.second<p2.second)return true;
}
return false;
}
};
class FoodRatings {
public:
FoodRatings(vector<string>& foods, vector<string>& cuisines, vector<int>& ratings) {
for(int i=0;i<foods.size();i++){
fm.emplace(foods[i],pair<int,string>(ratings[i],cuisines[i])); //将元素添加到fm中,键值为食物名称
cm[cuisines[i]].emplace(pair<int,string>(ratings[i],foods[i])); //将元素添加到cm中,键值为烹饪方式
}
}
void changeRating(string food, int newRating) {
pair<int,string>&p=fm[food]; //如果不用引用的话,后面就无法对fm中食物的评分进行修改,那么下一次要想删除cm中set的元素,会由于没有更新fm中的评分而找不到set中对应元素,造成删除失败,从而影响找到评分最高的
cm[p.second].erase(pair<int,string>(p.first,food)); //删除set中想要修改的食物评分对应的元素
p.first=newRating; //修改fm中食物的评分
cm[p.second].emplace(pair<int,string>(p.first,food)); //将新的食物名成和评分添加到对应的烹饪方式里面,更新cm
}
string highestRated(string cuisine) {
return (cm[cuisine].begin())->second; //由于cm中set是按自定义排序的,所以其键值(烹饪方式)下的set的第一个元素的第二个值就是所求
}
unordered_map<string,set<pair<int,string>,mycompare>>cm; //用来记录每种烹饪方式所对应的食物的评分和名字
unordered_map<string,pair<int,string>>fm; //用来记录每种食物的名字所对应的食物评分和烹饪方式(这是用于辅助cm的,因为在修改食物评分时需要对cm中set进行删除和添加,而参数只有食物名字和想要修改的评分,而没有提供该食物原来的评分以及烹饪方式)
};