Skip to content

Commit 77158a6

Browse files
chore: add LeetCode daily solution
1 parent 8d24724 commit 77158a6

File tree

5 files changed

+150
-0
lines changed

5 files changed

+150
-0
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Design a Food Rating System (Medium)
2+
3+
**Problem ID:** 2353
4+
**Date:** 2025-09-17
5+
**Link:** https://leetcode.com/problems/design-a-food-rating-system/
6+
7+
## Approach
8+
9+
To solve the problem of designing a food rating system, we need to efficiently handle two operations: changing the rating of a food item and retrieving the highest-rated food item for a specific cuisine. Here’s a structured approach to tackle this problem:
10+
11+
### Main Idea
12+
The core idea is to maintain a mapping of food items to their ratings and cuisines, while also keeping track of the highest-rated food items for each cuisine. This allows us to quickly update ratings and retrieve the highest-rated food efficiently.
13+
14+
### Data Structures
15+
1. **HashMap for Food Ratings**: Use a dictionary (or hash map) to store the food item as the key and its corresponding rating as the value. This allows O(1) time complexity for updating the rating of a food item.
16+
17+
2. **HashMap for Cuisines**: Use another dictionary to map each cuisine to a priority queue (or a sorted list) that contains food items sorted by their ratings. This allows us to efficiently retrieve the highest-rated food item for a given cuisine.
18+
19+
3. **Priority Queue (or Sorted List)**: Each cuisine's food items can be stored in a priority queue (or sorted list) to enable efficient retrieval of the highest-rated food item. In Python, this can be implemented using a min-heap, where we store negative ratings to simulate a max-heap behavior.
20+
21+
### Operations
22+
- **Initialization**: During the initialization of the `FoodRatings` class, populate the food ratings map and the cuisine map, filling the priority queues with food items based on their initial ratings.
23+
24+
- **Change Rating**: When the `changeRating` method is called:
25+
- Update the food's rating in the food ratings map.
26+
- Remove the old rating of the food from the corresponding cuisine's priority queue and insert the new rating. This can be done efficiently if we maintain a structure that allows for quick updates (like a balanced tree or a heap).
27+
28+
- **Highest Rated**: When the `highestRated` method is called:
29+
- Simply retrieve the top item from the priority queue associated with the specified cuisine. This operation is efficient due to the properties of the priority queue.
30+
31+
### Complexity
32+
- **Initialization**: O(n log n) due to inserting `n` food items into the priority queues.
33+
- **Change Rating**: O(log m) where `m` is the number of food items in the specific cuisine, due to the operations on the priority queue.
34+
- **Highest Rated**: O(1) for retrieving the highest-rated food item from the priority queue.
35+
36+
Overall, this approach ensures that both operations are efficient, making the system scalable to the problem's constraints. The use of hash maps and priority queues allows for quick access and updates, which is crucial given the potential number of operations.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import java.util.*;
2+
3+
class FoodRatings {
4+
private Map<String, Integer> foodRating;
5+
private Map<String, String> foodCuisine;
6+
private Map<String, TreeSet<String>> cuisineFoods;
7+
8+
public FoodRatings(String[] foods, String[] cuisines, int[] ratings) {
9+
foodRating = new HashMap<>();
10+
foodCuisine = new HashMap<>();
11+
cuisineFoods = new HashMap<>();
12+
13+
for (int i = 0; i < foods.length; i++) {
14+
foodRating.put(foods[i], ratings[i]);
15+
foodCuisine.put(foods[i], cuisines[i]);
16+
cuisineFoods.putIfAbsent(cuisines[i], new TreeSet<>((a, b) -> {
17+
if (foodRating.get(a).equals(foodRating.get(b))) {
18+
return a.compareTo(b);
19+
}
20+
return foodRating.get(b) - foodRating.get(a);
21+
}));
22+
cuisineFoods.get(cuisines[i]).add(foods[i]);
23+
}
24+
}
25+
26+
public void changeRating(String food, int newRating) {
27+
String cuisine = foodCuisine.get(food);
28+
TreeSet<String> foodsSet = cuisineFoods.get(cuisine);
29+
foodsSet.remove(food);
30+
foodRating.put(food, newRating);
31+
foodsSet.add(food);
32+
}
33+
34+
public String highestRated(String cuisine) {
35+
return cuisineFoods.get(cuisine).first();
36+
}
37+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
class FoodRatings {
2+
constructor(foods, cuisines, ratings) {
3+
this.foodMap = new Map();
4+
this.cuisineMap = new Map();
5+
this.foods = foods;
6+
7+
for (let i = 0; i < foods.length; i++) {
8+
this.foodMap.set(foods[i], { cuisine: cuisines[i], rating: ratings[i] });
9+
if (!this.cuisineMap.has(cuisines[i])) {
10+
this.cuisineMap.set(cuisines[i], []);
11+
}
12+
this.cuisineMap.get(cuisines[i]).push(foods[i]);
13+
}
14+
}
15+
16+
changeRating(food, newRating) {
17+
const foodInfo = this.foodMap.get(food);
18+
const cuisine = foodInfo.cuisine;
19+
foodInfo.rating = newRating;
20+
}
21+
22+
highestRated(cuisine) {
23+
const foodsInCuisine = this.cuisineMap.get(cuisine);
24+
let highestRatedFood = foodsInCuisine[0];
25+
let highestRating = this.foodMap.get(highestRatedFood).rating;
26+
27+
for (const food of foodsInCuisine) {
28+
const rating = this.foodMap.get(food).rating;
29+
if (rating > highestRating || (rating === highestRating && food < highestRatedFood)) {
30+
highestRatedFood = food;
31+
highestRating = rating;
32+
}
33+
}
34+
return highestRatedFood;
35+
}
36+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
from collections import defaultdict
2+
import heapq
3+
4+
class FoodRatings:
5+
6+
def __init__(self, foods: List[str], cuisines: List[str], ratings: List[int]):
7+
self.food_rating = {}
8+
self.cuisine_map = defaultdict(list)
9+
self.cuisine_heap = {}
10+
11+
for food, cuisine, rating in zip(foods, cuisines, ratings):
12+
self.food_rating[food] = rating
13+
self.cuisine_map[cuisine].append(food)
14+
if cuisine not in self.cuisine_heap:
15+
self.cuisine_heap[cuisine] = []
16+
heapq.heappush(self.cuisine_heap[cuisine], (-rating, food))
17+
18+
def changeRating(self, food: str, newRating: int) -> None:
19+
oldRating = self.food_rating[food]
20+
self.food_rating[food] = newRating
21+
cuisine = next(c for c, foods in self.cuisine_map.items() if food in foods)
22+
23+
# Update the heap
24+
heapq.heappush(self.cuisine_heap[cuisine], (-newRating, food))
25+
26+
# Remove the old rating from the heap
27+
while self.cuisine_heap[cuisine]:
28+
if -self.cuisine_heap[cuisine][0][0] == oldRating and self.cuisine_heap[cuisine][0][1] == food:
29+
heapq.heappop(self.cuisine_heap[cuisine])
30+
break
31+
else:
32+
heapq.heappop(self.cuisine_heap[cuisine])
33+
34+
def highestRated(self, cuisine: str) -> str:
35+
while self.cuisine_heap[cuisine]:
36+
rating, food = self.cuisine_heap[cuisine][0]
37+
if -rating == self.food_rating[food]:
38+
return food
39+
else:
40+
heapq.heappop(self.cuisine_heap[cuisine])

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,3 +149,4 @@ Each problem includes:
149149
- 2025-09-13 — [Find Most Frequent Vowel and Consonant](https://leetcode.com/problems/find-most-frequent-vowel-and-consonant/) (Easy) → `Easy/2025-09-13-3541-Find-Most-Frequent-Vowel-and-Consonant`
150150
- 2025-09-14 — [Vowel Spellchecker](https://leetcode.com/problems/vowel-spellchecker/) (Medium) → `Medium/2025-09-14-966-Vowel-Spellchecker`
151151
- 2025-09-15 — [Maximum Number of Words You Can Type](https://leetcode.com/problems/maximum-number-of-words-you-can-type/) (Easy) → `Easy/2025-09-15-1935-Maximum-Number-of-Words-You-Can-Type`
152+
- 2025-09-17 — [Design a Food Rating System](https://leetcode.com/problems/design-a-food-rating-system/) (Medium) → `Medium/2025-09-17-2353-Design-a-Food-Rating-System`

0 commit comments

Comments
 (0)