Design a food rating system that can do the following:
Implement the FoodRatings class:
FoodRatings(String[] foods, String[] cuisines, int[] ratings) Initializes the system. The food items are paired with their cuisines and ratings.void changeRating(String food, int newRating) Changes the rating of the food item.String highestRated(String cuisine) Returns the name of the food item that has the highest rating for the given cuisine. If there is a tie, return the lexicographically smaller name.1 <= foods.length <= 2 * 10^4foods[i].length == cuisines[i].length == ratings[i]1 <= foods[i].length, cuisines[i].length <= 101 <= ratings[i] <= 10^8foods[i], cuisines[i] consist of lowercase English letters and the ' ' space characterfoods[i], cuisines[i]` do not contain leading or trailing spacesAll foods[i] are distinct1 <= newRating <= 10^8At most 2 * 10^4 calls will be made to changeRating and highestRatedUse three maps:
foodCuisines: Maps food → cuisinefoodRating: Maps food → ratingcuisinesRatingFood: Maps cuisine → TreeSet of pairs (-rating, foodName)Store ratings as negative in the TreeSet, so the highest-rated food is always the first element (TreeSet sorts in ascending order, so -10 comes before -5).
Why this approach works:
Alternative approaches considered:
Example Input:
foods = ["kimchi", "miso", "sushi", "moussaka", "ramen", "bulgogi"]
cuisines = ["korean", "japanese", "japanese", "greek", "japanese", "korean"]
ratings = [9, 12, 8, 15, 14, 7]
Step-by-step execution:
Final Answer = "ramen"
import javafx.util.Pair;
import java.util.*;
public class FoodRatings {
    private Map<String, TreeSet<Pair<Integer, String>>> cuisinesRatingFood = new HashMap<>();
    private Map<String, String> foodCuisines = new HashMap<>();
    private Map<String, Integer> foodRating = new HashMap<>();
    public FoodRatings(String[] foods, String[] cuisines, int[] ratings) {
        for (int i = 0; i < foods.length; ++i) {
            foodCuisines.put(foods[i], cuisines[i]);
            foodRating.put(foods[i], ratings[i]);
            cuisinesRatingFood.computeIfAbsent(cuisines[i], e -> new TreeSet<>(
                    (a, b) -> a.getKey().equals(b.getKey()) 
                        ? a.getValue().compareTo(b.getValue()) 
                        : Integer.compare(a.getKey(), b.getKey())))
                    .add(new Pair<>(-ratings[i], foods[i]));
        }
    }
    public void changeRating(String food, int newRating) {
        int oldRating = foodRating.get(food);
        TreeSet<Pair<Integer, String>> cuisineSet = cuisinesRatingFood.get(foodCuisines.get(food));
        cuisineSet.remove(new Pair<>(-oldRating, food));
        foodRating.put(food, newRating);
        cuisineSet.add(new Pair<>(-newRating, food));
    }
    public String highestRated(String cuisine) {
        return cuisinesRatingFood.get(cuisine).first().getValue();
    }
}