2429. Design A Food Rating System¶
Difficulty: Medium
LeetCode Problem View on GitHub
2429. Design a Food Rating System
Medium
Design a food rating system that can do the following:
- Modify the rating of a food item listed in the system.
- Return the highest-rated food item for a type of cuisine in the system.
Implement the FoodRatings class:
FoodRatings(String[] foods, String[] cuisines, int[] ratings)Initializes the system. The food items are described byfoods,cuisinesandratings, all of which have a length ofn.foods[i]is the name of theithfood,cuisines[i]is the type of cuisine of theithfood, andratings[i]is the initial rating of theithfood.
void changeRating(String food, int newRating)Changes the rating of the food item with the namefood.String highestRated(String cuisine)Returns the name of the food item that has the highest rating for the given type ofcuisine. If there is a tie, return the item with the lexicographically smaller name.
Note that a string x is lexicographically smaller than string y if x comes before y in dictionary order, that is, either x is a prefix of y, or if i is the first position such that x[i] != y[i], then x[i] comes before y[i] in alphabetic order.
Example 1:
Input
["FoodRatings", "highestRated", "highestRated", "changeRating", "highestRated", "changeRating", "highestRated"]
[[["kimchi", "miso", "sushi", "moussaka", "ramen", "bulgogi"], ["korean", "japanese", "japanese", "greek", "japanese", "korean"], [9, 12, 8, 15, 14, 7]], ["korean"], ["japanese"], ["sushi", 16], ["japanese"], ["ramen", 16], ["japanese"]]
Output
[null, "kimchi", "ramen", null, "sushi", null, "ramen"]
Explanation
FoodRatings foodRatings = new FoodRatings(["kimchi", "miso", "sushi", "moussaka", "ramen", "bulgogi"], ["korean", "japanese", "japanese", "greek", "japanese", "korean"], [9, 12, 8, 15, 14, 7]);
foodRatings.highestRated("korean"); // return "kimchi"
// "kimchi" is the highest rated korean food with a rating of 9.
foodRatings.highestRated("japanese"); // return "ramen"
// "ramen" is the highest rated japanese food with a rating of 14.
foodRatings.changeRating("sushi", 16); // "sushi" now has a rating of 16.
foodRatings.highestRated("japanese"); // return "sushi"
// "sushi" is the highest rated japanese food with a rating of 16.
foodRatings.changeRating("ramen", 16); // "ramen" now has a rating of 16.
foodRatings.highestRated("japanese"); // return "ramen"
// Both "sushi" and "ramen" have a rating of 16.
// However, "ramen" is lexicographically smaller than "sushi".
Constraints:
1 <= n <= 2 * 104n == foods.length == cuisines.length == ratings.length1 <= foods[i].length, cuisines[i].length <= 10foods[i],cuisines[i]consist of lowercase English letters.1 <= ratings[i] <= 108- All the strings in
foodsare distinct. foodwill be the name of a food item in the system across all calls tochangeRating.cuisinewill be a type of cuisine of at least one food item in the system across all calls tohighestRated.- At most
2 * 104calls in total will be made tochangeRatingandhighestRated.
Solution¶
class FoodRatings {
private HashMap<String, TreeSet<Pair>> map;
private HashMap<String, ArrayList<String>> foodMap; // currentFood is present in which of the cousines;
private HashMap<String, Integer> ratingMap; // Currently what is the rating of each food;
static class Pair {
String food;
int rating;
public Pair(String food, int rating) {
this.food = food;
this.rating = rating;
}
@Override
public String toString() {
return "(" + food + " " + rating + ")";
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null || getClass() != obj.getClass())
return false;
Pair current = (Pair)(obj);
return current.food.equals(food) && current.rating == rating;
}
@Override
public int hashCode() {
return Objects.hash(food, rating);
}
}
static class customSort implements Comparator<Pair> {
@Override
public int compare(Pair first, Pair second) {
int op1 = Integer.compare(second.rating, first.rating);
if (op1 != 0)
return op1;
return first.food.compareTo(second.food);
}
}
public FoodRatings(String[] foods, String[] cuisines, int[] ratings) {
int n = foods.length;
map = new HashMap<>();
foodMap = new HashMap<>();
ratingMap = new HashMap<>();
for (int i = 0; i < n; i++) {
String type = cuisines[i], food = foods[i];
if (!map.containsKey(type))
map.put(type, new TreeSet<Pair>(new customSort()));
map.get(type).add(new Pair(foods[i], ratings[i]));
if (!foodMap.containsKey(food))
foodMap.put(food, new ArrayList<>());
foodMap.get(food).add(cuisines[i]);
ratingMap.put(foods[i], ratings[i]);
}
}
public void changeRating(String food, int newRating) {
ArrayList<String> ids = new ArrayList<>();
ids = foodMap.get(food);
for (int i = 0; i < ids.size(); i++) {
TreeSet<Pair> currCuines = new TreeSet<>();
currCuines = map.get(ids.get(i));
//update the food and its rating;
int currRating = ratingMap.get(food);
currCuines.remove(new Pair(food, currRating));
currCuines.add(new Pair(food, newRating));
map.put(ids.get(i), currCuines);
ratingMap.put(food, newRating);
}
}
public String highestRated(String cuisine) {
TreeSet<Pair> curr = map.get(cuisine);
return curr.first().food;
}
}
/**
* Your FoodRatings object will be instantiated and called as such:
* FoodRatings obj = new FoodRatings(foods, cuisines, ratings);
* obj.changeRating(food,newRating);
* String param_2 = obj.highestRated(cuisine);
*/
Complexity Analysis¶
- Time Complexity:
O(?) - Space Complexity:
O(?)
Approach¶
Detailed explanation of the approach will be added here