2353. 设计食物评分系统

245 阅读1分钟

题目:
leetcode.cn/problems/de…
算法:
方法一:堆+懒删除
总体思路:

  • HighestRated要根据cusine找到评分最高的菜单,这显然是用堆来实现最好,每个cuisine使用一个堆。
  • 另外ChangeRating函数要求按food修改评分,修改之后堆如何重新平衡是需要解决的问题。

我们使用懒删除来解决这个问题:用一个map[food]newRating记录food最新的评分,每次ChangeRating时更新map[food]newRating,并且往heap中插入一条最新的评分pair{food, newRating}。这样heap中对于food维护了新旧两条数据,当堆顶的数据的rating等于map[food]中的分数时,才是最新的数据,不等则出heap即可。

import "container/heap"
type FoodRatings struct {
    cr map[string]*hp
    fr map[string]*pair
}


func Constructor(foods []string, cuisines []string, ratings []int) FoodRatings {
    foodRatings := FoodRatings{
        cr: make(map[string]*hp),
        fr: make(map[string]*pair),
    }
    for i := range foods {
        h, ok := foodRatings.cr[cuisines[i]]
        if !ok {
            h = &hp{}
            foodRatings.cr[cuisines[i]] = h
        }
        heap.Push(h, pair{food:foods[i], rating:ratings[i]})
        foodRatings.fr[foods[i]] = &pair{cuisine:cuisines[i], rating:ratings[i]}
    }
    return foodRatings
}


func (this *FoodRatings) ChangeRating(food string, newRating int)  {
    this.fr[food].rating = newRating
    h := this.cr[this.fr[food].cuisine]
    heap.Push(h, pair{food:food, rating:newRating})
}


func (this *FoodRatings) HighestRated(cuisine string) string {
    h := this.cr[cuisine]
    for (*h).Len() > 0 && (*h)[0].rating != this.fr[(*h)[0].food].rating{
        heap.Pop(h)
    }
    return (*h)[0].food 
}

type pair struct {
    food string
    rating int
    cuisine string
}

type hp []pair
func (h hp) Less(i, j int) bool {
    if h[i].rating == h[j].rating {
        return h[i].food < h[j].food
    }
    return h[i].rating > h[j].rating
}
func (h hp) Len() int  {
    return len(h)
}
func (h hp) Swap(i, j int)  {
    h[i], h[j] = h[j], h[i]
}
func(h *hp) Push(x interface{}) {
    *h = append(*h, x.(pair))
}
func(h *hp) Pop() interface{} {
    old := *h
    n := len(old)
    x := old[n - 1]
    *h = old[:n -1]
    return x
}

/**
 * Your FoodRatings object will be instantiated and called as such:
 * obj := Constructor(foods, cuisines, ratings);
 * obj.ChangeRating(food,newRating);
 * param_2 := obj.HighestRated(cuisine);
 */