@@ -95,30 +95,42 @@ foodRatings.highestRated("japanese"); // 返回 "ramen"
95
95
96
96
<!-- solution:start -->
97
97
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)$。
99
111
100
112
<!-- tabs:start -->
101
113
102
114
#### Python3
103
115
104
116
``` python
105
117
class 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 ])))
109
118
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)
113
125
114
126
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))
119
131
120
132
def highestRated (self , cuisine : str ) -> str :
121
- return self .t [cuisine][0 ][1 ]
133
+ return self .d [cuisine][0 ][1 ]
122
134
123
135
124
136
# Your FoodRatings object will be instantiated and called as such:
@@ -127,36 +139,78 @@ class FoodRatings:
127
139
# param_2 = obj.highestRated(cuisine)
128
140
```
129
141
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
+
130
186
#### C++
131
187
132
188
``` cpp
133
- using pis = pair<int , string>;
134
-
135
189
class FoodRatings {
136
- map<string, pis> mp;
137
- map<string, set<pis >> t;
138
-
139
190
public:
140
191
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};
147
197
}
148
198
}
149
199
150
200
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} );
155
205
}
156
206
157
207
string highestRated (string cuisine) {
158
- return t [ cuisine] .begin()->second;
208
+ return d [ cuisine] .begin()->second;
159
209
}
210
+
211
+ private:
212
+ unordered_map<string, set<pair<int, string>>> d;
213
+ unordered_map<string, pair<int, string>> g;
160
214
};
161
215
162
216
/**
@@ -167,6 +221,65 @@ public:
167
221
* /
168
222
```
169
223
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
+
170
283
<!-- tabs:end -->
171
284
172
285
<!-- solution:end -->
0 commit comments