@@ -95,30 +95,42 @@ foodRatings.highestRated("japanese"); // 返回 "ramen"
9595
9696<!-- solution:start -->
9797
98- ### 方法一
98+ ### 方法一:哈希表 + 有序集合
99+
100+ 我们可以使用哈希表 $\textit{d}$ 来存储每种烹饪方式下的食物,其中键是烹饪方式,值是一个有序集合,有序集合的每个元素是一个二元组 $(\textit{rating}, \textit{food})$,按照评分从高到低排序,如果评分相同,则按照食物名字的字典序从小到大排序。
101+
102+ 我们还可以使用哈希表 $\textit{g}$ 来存储每种食物的评分和烹饪方式。即 $\textit{g}[ \textit{food}] = (\textit{rating}, \textit{cuisine})$。
103+
104+ 在构造函数中,我们遍历 $\textit{foods}$、$\textit{cuisines}$ 和 $\textit{ratings}$,将每种食物的评分和烹饪方式存储到 $\textit{d}$ 和 $\textit{g}$ 中。
105+
106+ 在 $\textit{changeRating}$ 函数中,我们首先获取食物 $\textit{food}$ 的原评分 $\textit{oldRating}$ 和烹饪方式 $\textit{cuisine}$,然后更新 $\textit{g}[ \textit{food}] $ 的评分为 $\textit{newRating}$,并从 $\textit{d}[ \textit{cuisine}] $ 中删除 $(\textit{oldRating}, \textit{food})$,并将 $(\textit{newRating}, \textit{food})$ 添加到 $\textit{d}[ \textit{cuisine}] $ 中。
107+
108+ 在 $\textit{highestRated}$ 函数中,我们直接返回 $\textit{d}[ \textit{cuisine}] $ 的第一个元素的食物名字即可。
109+
110+ 时间复杂度方面,构造函数的时间复杂度为 $O(n \log n)$,其中 $n$ 是食物的数量。其余操作的时间复杂度为 $O(\log n)$。空间复杂度为 $O(n)$。
99111
100112<!-- tabs:start -->
101113
102114#### Python3
103115
104116``` python
105117class FoodRatings :
106- def __init__ (self , foods : List[str ], cuisines : List[str ], ratings : List[int ]):
107- self .mp = {}
108- self .t = defaultdict(lambda : SortedSet(key = lambda x : (- x[0 ], x[1 ])))
109118
110- for a, b, c in zip (foods, cuisines, ratings):
111- self .mp[a] = (b, c)
112- self .t[b].add((c, a))
119+ def __init__ (self , foods : List[str ], cuisines : List[str ], ratings : List[int ]):
120+ self .d = defaultdict(SortedList)
121+ self .g = {}
122+ for food, cuisine, rating in zip (foods, cuisines, ratings):
123+ self .d[cuisine].add((- rating, food))
124+ self .g[food] = (rating, cuisine)
113125
114126 def changeRating (self , food : str , newRating : int ) -> None :
115- b, c = self .mp [food]
116- self .mp [food] = (b, newRating )
117- self .t[b ].remove((c , food))
118- self .t[b ].add((newRating, food))
127+ oldRating, cuisine = self .g [food]
128+ self .g [food] = (newRating, cuisine )
129+ self .d[cuisine ].remove((- oldRating , food))
130+ self .d[cuisine ].add((- newRating, food))
119131
120132 def highestRated (self , cuisine : str ) -> str :
121- return self .t [cuisine][0 ][1 ]
133+ return self .d [cuisine][0 ][1 ]
122134
123135
124136# Your FoodRatings object will be instantiated and called as such:
@@ -127,36 +139,78 @@ class FoodRatings:
127139# param_2 = obj.highestRated(cuisine)
128140```
129141
142+ #### Java
143+
144+ ``` java
145+ class FoodRatings {
146+ private Map<String , TreeSet<Pair<Integer , String > > > d = new HashMap<> ();
147+ private Map<String , Pair<Integer , String > > g = new HashMap<> ();
148+ private final Comparator<Pair<Integer , String > > cmp = (a, b) - > {
149+ if (! a. getKey(). equals(b. getKey())) {
150+ return b. getKey(). compareTo(a. getKey());
151+ }
152+ return a. getValue(). compareTo(b. getValue());
153+ };
154+
155+ public FoodRatings (String [] foods , String [] cuisines , int [] ratings ) {
156+ for (int i = 0 ; i < foods. length; ++ i) {
157+ String food = foods[i], cuisine = cuisines[i];
158+ int rating = ratings[i];
159+ d. computeIfAbsent(cuisine, k - > new TreeSet<> (cmp)). add(new Pair<> (rating, food));
160+ g. put(food, new Pair<> (rating, cuisine));
161+ }
162+ }
163+
164+ public void changeRating (String food , int newRating ) {
165+ Pair<Integer , String > old = g. get(food);
166+ int oldRating = old. getKey();
167+ String cuisine = old. getValue();
168+ g. put(food, new Pair<> (newRating, cuisine));
169+ d. get(cuisine). remove(new Pair<> (oldRating, food));
170+ d. get(cuisine). add(new Pair<> (newRating, food));
171+ }
172+
173+ public String highestRated (String cuisine ) {
174+ return d. get(cuisine). first(). getValue();
175+ }
176+ }
177+
178+ /**
179+ * Your FoodRatings object will be instantiated and called as such:
180+ * FoodRatings obj = new FoodRatings(foods, cuisines, ratings);
181+ * obj.changeRating(food,newRating);
182+ * String param_2 = obj.highestRated(cuisine);
183+ */
184+ ```
185+
130186#### C++
131187
132188``` cpp
133- using pis = pair<int , string>;
134-
135189class FoodRatings {
136- map<string, pis> mp;
137- map<string, set<pis >> t;
138-
139190public:
140191 FoodRatings(vector<string >& foods, vector<string >& cuisines, vector<int >& ratings) {
141- int n = foods.size();
142- for (int i = 0; i < n; ++i) {
143- string a = foods[ i] , b = cuisines[ i] ;
144- int c = ratings[ i] ;
145- mp[ a] = pis(c, b);
146- t[ b] .insert(pis(-c, a));
192+ for (int i = 0; i < foods.size(); ++i) {
193+ string food = foods[ i] , cuisine = cuisines[ i] ;
194+ int rating = ratings[ i] ;
195+ d[ cuisine] .insert({-rating, food});
196+ g[ food] = {rating, cuisine};
147197 }
148198 }
149199
150200 void changeRating(string food, int newRating) {
151- pis& p = mp [food];
152- t[p.second].erase(pis(-p.first, food)) ;
153- p.first = newRating ;
154- t[p.second ].insert(pis(-p.first , food) );
201+ auto [oldRating, cuisine] = g [food];
202+ g[food] = {newRating, cuisine} ;
203+ d[cuisine].erase({-oldRating, food}) ;
204+ d[cuisine ].insert({-newRating , food} );
155205 }
156206
157207 string highestRated (string cuisine) {
158- return t [ cuisine] .begin()->second;
208+ return d [ cuisine] .begin()->second;
159209 }
210+
211+ private:
212+ unordered_map<string, set<pair<int, string>>> d;
213+ unordered_map<string, pair<int, string>> g;
160214};
161215
162216/**
@@ -167,6 +221,65 @@ public:
167221 * /
168222```
169223
224+ #### Go
225+
226+ ```go
227+ import (
228+ "github.com/emirpasic/gods/v2/trees/redblacktree"
229+ )
230+
231+ type pair struct {
232+ rating int
233+ food string
234+ }
235+
236+ type FoodRatings struct {
237+ d map[string]*redblacktree.Tree[pair, struct{}]
238+ g map[string]pair
239+ }
240+
241+ func Constructor(foods []string, cuisines []string, ratings []int) FoodRatings {
242+ d := make(map[string]*redblacktree.Tree[pair, struct{}])
243+ g := make(map[string]pair)
244+
245+ for i, food := range foods {
246+ rating, cuisine := ratings[i], cuisines[i]
247+ g[food] = pair{rating, cuisine}
248+
249+ if d[cuisine] == nil {
250+ d[cuisine] = redblacktree.NewWith[pair, struct{}](func(a, b pair) int {
251+ return cmp.Or(b.rating-a.rating, strings.Compare(a.food, b.food))
252+ })
253+ }
254+ d[cuisine].Put(pair{rating, food}, struct{}{})
255+ }
256+
257+ return FoodRatings{d, g}
258+ }
259+
260+ func (this *FoodRatings) ChangeRating(food string, newRating int) {
261+ p := this.g[food]
262+ t := this.d[p.food]
263+
264+ t.Remove(pair{p.rating, food})
265+ t.Put(pair{newRating, food}, struct{}{})
266+
267+ p.rating = newRating
268+ this.g[food] = p
269+ }
270+
271+ func (this *FoodRatings) HighestRated(cuisine string) string {
272+ return this.d[cuisine].Left().Key.food
273+ }
274+
275+ /**
276+ * Your FoodRatings object will be instantiated and called as such:
277+ * obj := Constructor(foods, cuisines, ratings);
278+ * obj.ChangeRating(food,newRating);
279+ * param_2 := obj.HighestRated(cuisine);
280+ */
281+ ```
282+
170283<!-- tabs:end -->
171284
172285<!-- solution:end -->
0 commit comments