Skip to content

Commit

Permalink
Merge pull request #714 from 0xff-dev/2353
Browse files Browse the repository at this point in the history
Add solution and test-cases for problem 2353
  • Loading branch information
6boris authored Dec 18, 2023
2 parents 6a208da + f92a45e commit 4bee3a6
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 28 deletions.
51 changes: 35 additions & 16 deletions leetcode/2301-2400/2353.Design-a-Food-Rating-System/README.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,47 @@
# [2353.Design a Food Rating System][title]

> [!WARNING|style:flat]
> This question is temporarily unanswered if you have good ideas. Welcome to [Create Pull Request PR](https://github.com/kylesliu/awesome-golang-algorithm)
## Description
Design a food rating system that can do the following:

**Example 1:**
- **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.

```
Input: a = "11", b = "1"
Output: "100"
```
Implement the `FoodRatings` class:

## 题意
> ...
- `FoodRatings(String[] foods, String[] cuisines, int[] ratings)` Initializes the system. The food items are described by `foods`, `cuisines` and `ratings`, all of which have a length of `n`.

## 题解
- `foods[i]` is the name of the i<sup>th</sup> food,
- `cuisines[i]` is the type of cuisine of the i<sup>th</sup> food, and
- `ratings[i]` is the initial rating of the i<sup>th</sup> food.

### 思路1
> ...
Design a Food Rating System
```go
```
- `void changeRating(String food, int newRating)` Changes the rating of the food item with the name `food`.
- `String highestRated(String cuisine)` Returns the name of the food item that has the highest rating for the given type of `cuisine`. 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".
```

## 结语

Expand Down
102 changes: 101 additions & 1 deletion leetcode/2301-2400/2353.Design-a-Food-Rating-System/Solution.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,105 @@
package Solution

func Solution(x bool) bool {
import (
"container/heap"
)

type fr struct {
name string
rating int
index *int
}
type frs []fr

func (f *frs) Len() int {
return len(*f)
}

func (f *frs) Swap(i, j int) {
*(*f)[i].index = j
*(*f)[j].index = i
(*f)[i], (*f)[j] = (*f)[j], (*f)[i]
}

func (f *frs) Less(i, j int) bool {
a := (*f)[i]
b := (*f)[j]
if a.rating == b.rating {
return a.name < b.name
}
return a.rating > b.rating
}

func (f *frs) Push(x interface{}) {
*f = append(*f, x.(fr))
}

func (f *frs) Pop() interface{} {
old := *f
l := len(old)
x := old[l-1]
*f = old[:l-1]
return x
}

type FoodRatings struct {
// Record the food's index in the heap via a pointer,
// which can be modified synchronously
indies map[string]*int
// Record the cusisine to which the food belongs
f2c map[string]string
// each cuisine maintains a heap
h map[string]*frs
}

func Constructor2353(foods []string, cuisines []string, ratings []int) FoodRatings {
r := FoodRatings{indies: make(map[string]*int), f2c: make(map[string]string), h: make(map[string]*frs)}
for idx, cuisine := range cuisines {
r.f2c[foods[idx]] = cuisine
if _, ok := r.h[cuisine]; !ok {
r.h[cuisine] = &frs{}
}

l := r.h[cuisine].Len()
r.indies[foods[idx]] = &l
heap.Push(r.h[cuisine], fr{name: foods[idx], rating: ratings[idx], index: &l})
}
return r
}

func (this *FoodRatings) ChangeRating(food string, newRating int) {
// get the index of the food in the heap
curIndex := this.indies[food]
// get the cuisine of food
cuisine := this.f2c[food]
// change rating
arr := this.h[cuisine]
(*arr)[*curIndex].rating = newRating
this.h[cuisine] = arr
// fix heap
heap.Fix(this.h[cuisine], *curIndex)
}

func (this *FoodRatings) HighestRated(cuisine string) string {
x := this.h[cuisine]
return (*x)[0].name
}

type opt struct {
name string
commonStr string
rating int
}

func Solution(foods []string, cuisines []string, ratings []int, opts []opt) []string {
c := Constructor2353(foods, cuisines, ratings)
ans := make([]string, 0)
for _, op := range opts {
if op.name == "h" {
ans = append(ans, c.HighestRated(op.commonStr))
continue
}
c.ChangeRating(op.commonStr, op.rating)
}
return ans
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,40 @@ import (
func TestSolution(t *testing.T) {
// 测试用例
cases := []struct {
name string
inputs bool
expect bool
name string
foods, cuisines []string
ratings []int
opts []opt
expect []string
}{
{"TestCase", true, true},
{"TestCase", true, true},
{"TestCase", false, false},
{"TestCase1", []string{"kimchi", "miso", "sushi", "moussaka", "ramen", "bulgogi"},
[]string{"korean", "japanese", "japanese", "greek", "japanese", "korean"}, []int{9, 12, 8, 15, 14, 7},
[]opt{
{name: "h", commonStr: "korean"},
{name: "h", commonStr: "japanese"},
{name: "c", commonStr: "sushi", rating: 16},
{name: "h", commonStr: "japanese"},
{name: "c", commonStr: "ramen", rating: 16},
{name: "h", commonStr: "japanese"}},
[]string{"kimchi", "ramen", "sushi", "ramen"}},
}

// 开始测试
for i, c := range cases {
t.Run(c.name+" "+strconv.Itoa(i), func(t *testing.T) {
got := Solution(c.inputs)
got := Solution(c.foods, c.cuisines, c.ratings, c.opts)
if !reflect.DeepEqual(got, c.expect) {
t.Fatalf("expected: %v, but got: %v, with inputs: %v",
c.expect, got, c.inputs)
t.Fatalf("expected: %v, but got: %v, with inputs: %v %v %v %v",
c.expect, got, c.foods, c.cuisines, c.ratings, c.opts)
}
})
}
}

// 压力测试
// 压力测试
func BenchmarkSolution(b *testing.B) {
}

// 使用案列
// 使用案列
func ExampleSolution() {
}

0 comments on commit 4bee3a6

Please sign in to comment.