From 7845ccb594ace0f605f2353b2f638ebb398b1bf2 Mon Sep 17 00:00:00 2001 From: 0xff-dev Date: Sat, 4 Oct 2025 17:31:03 +0800 Subject: [PATCH] Add solution and test-cases for problem 1172 --- .../1172.Dinner-Plate-Stacks/README.md | 64 ++++-- .../1172.Dinner-Plate-Stacks/Solution.go | 183 +++++++++++++++++- .../1172.Dinner-Plate-Stacks/Solution_test.go | 35 +++- 3 files changed, 254 insertions(+), 28 deletions(-) diff --git a/leetcode/1101-1200/1172.Dinner-Plate-Stacks/README.md b/leetcode/1101-1200/1172.Dinner-Plate-Stacks/README.md index 8a37e815b..a07b241e4 100644 --- a/leetcode/1101-1200/1172.Dinner-Plate-Stacks/README.md +++ b/leetcode/1101-1200/1172.Dinner-Plate-Stacks/README.md @@ -1,28 +1,58 @@ # [1172.Dinner Plate Stacks][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 +You have an infinite number of stacks arranged in a row and numbered (left to right) from `0`, each of the stacks has the same maximum capacity. -**Example 1:** - -``` -Input: a = "11", b = "1" -Output: "100" -``` +Implement the `DinnerPlates` class: -## 题意 -> ... +- `DinnerPlates(int capacity)` Initializes the object with the maximum capacity of the stacks `capacity`. +- `void push(int val)` Pushes the given integer `val` into the leftmost stack with a size less than `capacity`. +- `int pop()` Returns the value at the top of the rightmost non-empty stack and removes it from that stack, and returns `-1` if all the stacks are empty. +- `int popAtStack(int index)` Returns the value at the top of the stack with the given `index` index and removes it from that stack or returns `-1` if the stack with that given index is empty. -## 题解 +**Example 1:** -### 思路1 -> ... -Dinner Plate Stacks -```go ``` - +Input +["DinnerPlates", "push", "push", "push", "push", "push", "popAtStack", "push", "push", "popAtStack", "popAtStack", "pop", "pop", "pop", "pop", "pop"] +[[2], [1], [2], [3], [4], [5], [0], [20], [21], [0], [2], [], [], [], [], []] +Output +[null, null, null, null, null, null, 2, null, null, 20, 21, 5, 4, 3, 1, -1] + +Explanation: +DinnerPlates D = DinnerPlates(2); // Initialize with capacity = 2 +D.push(1); +D.push(2); +D.push(3); +D.push(4); +D.push(5); // The stacks are now: 2 4 + 1 3 5 + ﹈ ﹈ ﹈ +D.popAtStack(0); // Returns 2. The stacks are now: 4 + 1 3 5 + ﹈ ﹈ ﹈ +D.push(20); // The stacks are now: 20 4 + 1 3 5 + ﹈ ﹈ ﹈ +D.push(21); // The stacks are now: 20 4 21 + 1 3 5 + ﹈ ﹈ ﹈ +D.popAtStack(0); // Returns 20. The stacks are now: 4 21 + 1 3 5 + ﹈ ﹈ ﹈ +D.popAtStack(2); // Returns 21. The stacks are now: 4 + 1 3 5 + ﹈ ﹈ ﹈ +D.pop() // Returns 5. The stacks are now: 4 + 1 3 + ﹈ ﹈ +D.pop() // Returns 4. The stacks are now: 1 3 + ﹈ ﹈ +D.pop() // Returns 3. The stacks are now: 1 + ﹈ +D.pop() // Returns 1. There are no stacks. +D.pop() // Returns -1. There are still no stacks. +``` ## 结语 diff --git a/leetcode/1101-1200/1172.Dinner-Plate-Stacks/Solution.go b/leetcode/1101-1200/1172.Dinner-Plate-Stacks/Solution.go index d115ccf5e..0af0ba61e 100644 --- a/leetcode/1101-1200/1172.Dinner-Plate-Stacks/Solution.go +++ b/leetcode/1101-1200/1172.Dinner-Plate-Stacks/Solution.go @@ -1,5 +1,186 @@ package Solution -func Solution(x bool) bool { +import "container/heap" + +type heapItem1172 struct { + stack []int + + index, sourceIndex int +} + +type leftNotFullHeap struct { + data []*heapItem1172 + capacity int +} + +func (h *leftNotFullHeap) Len() int { + return len(h.data) +} + +func (h *leftNotFullHeap) Less(i, j int) bool { + a, b := h.data[i], h.data[j] + la, lb := len(a.stack), len(b.stack) + if la == h.capacity { + return false + } + if lb == h.capacity { + return true + } + return a.sourceIndex < b.sourceIndex +} + +func (h *leftNotFullHeap) Swap(i, j int) { + h.data[i], h.data[j] = h.data[j], h.data[i] + h.data[i].index = i + h.data[j].index = j +} + +func (h *leftNotFullHeap) Push(x any) { + item := x.(*heapItem1172) + l := len(h.data) + item.index = l + h.data = append(h.data, item) +} + +func (h *leftNotFullHeap) Pop() any { + old := h.data + l := len(old) + x := old[l-1] + h.data = old[:l-1] return x } + +type rightHeapItem1172 struct { + sourceIndex, index int +} +type rightNotEmptyHeap struct { + data []*rightHeapItem1172 + list *[]*heapItem1172 +} + +func (h *rightNotEmptyHeap) Len() int { + return len(h.data) +} + +func (h *rightNotEmptyHeap) Less(i, j int) bool { + a, b := h.data[i], h.data[j] + ia, ib := (*h.list)[a.sourceIndex], (*h.list)[b.sourceIndex] + li, lj := len(ia.stack), len(ib.stack) + if li == 0 && lj == 0 || (li != 0 && lj != 0) { + return a.sourceIndex > b.sourceIndex + } + return li != 0 +} + +func (h *rightNotEmptyHeap) Swap(i, j int) { + h.data[i], h.data[j] = h.data[j], h.data[i] + h.data[i].index = i + h.data[j].index = j +} + +func (h *rightNotEmptyHeap) Push(x any) { + item := x.(*rightHeapItem1172) + item.index = len(h.data) + h.data = append(h.data, item) +} + +func (h *rightNotEmptyHeap) Pop() any { + l := len(h.data) + x := h.data[l-1] + h.data = h.data[:l-1] + return x +} + +type DinnerPlates struct { + leftNotFull *leftNotFullHeap + rightNotEmpty *rightNotEmptyHeap + capacity int + leftIndies *[]*heapItem1172 + + rightIndies map[int]*rightHeapItem1172 +} + +func Constructor(capacity int) DinnerPlates { + indies := make([]*heapItem1172, 0) + return DinnerPlates{ + leftNotFull: &leftNotFullHeap{ + data: make([]*heapItem1172, 0), + capacity: capacity, + }, + rightNotEmpty: &rightNotEmptyHeap{ + data: make([]*rightHeapItem1172, 0), + list: &indies, + }, + capacity: capacity, + leftIndies: &indies, + rightIndies: make(map[int]*rightHeapItem1172), + } +} + +func (this *DinnerPlates) Push(val int) { + if len(this.leftNotFull.data) == 0 || len(this.leftNotFull.data[0].stack) == this.capacity { + sourceIndex := len(this.leftNotFull.data) + leftItem := &heapItem1172{ + stack: []int{val}, + sourceIndex: sourceIndex, + } + rightItem := &rightHeapItem1172{ + sourceIndex: sourceIndex, + } + this.rightIndies[sourceIndex] = rightItem + + *this.leftIndies = append(*this.leftIndies, leftItem) + heap.Push(this.leftNotFull, leftItem) + heap.Push(this.rightNotEmpty, rightItem) + return + } + zero := this.leftNotFull.data[0] + zero.stack = append(zero.stack, val) + heap.Fix(this.leftNotFull, 0) + heap.Fix(this.rightNotEmpty, this.rightIndies[zero.sourceIndex].index) +} + +func (this *DinnerPlates) Pop() int { + top := this.rightNotEmpty.data[0] + return this.PopAtStack(top.sourceIndex) +} + +func (this *DinnerPlates) PopAtStack(index int) int { + if index < 0 || index >= len(*this.leftIndies) { + return -1 + } + v := (*this.leftIndies)[index] + l := len(v.stack) + if l == 0 { + return -1 + } + x := v.stack[l-1] + v.stack = v.stack[:l-1] + heap.Fix(this.leftNotFull, v.index) + heap.Fix(this.rightNotEmpty, this.rightIndies[v.sourceIndex].index) + return x +} + +type opt struct { + name string + i int +} + +func Solution(capacity int, opts []opt) []int { + c := Constructor(capacity) + var ret []int + for _, op := range opts { + if op.name == "push" { + c.Push(op.i) + continue + } + if op.name == "popAtStack" { + ret = append(ret, c.PopAtStack(op.i)) + continue + } + if op.name == "pop" { + ret = append(ret, c.Pop()) + } + } + return ret +} diff --git a/leetcode/1101-1200/1172.Dinner-Plate-Stacks/Solution_test.go b/leetcode/1101-1200/1172.Dinner-Plate-Stacks/Solution_test.go index 14ff50eb4..f19c42d5c 100644 --- a/leetcode/1101-1200/1172.Dinner-Plate-Stacks/Solution_test.go +++ b/leetcode/1101-1200/1172.Dinner-Plate-Stacks/Solution_test.go @@ -10,30 +10,45 @@ func TestSolution(t *testing.T) { // 测试用例 cases := []struct { name string - inputs bool - expect bool + inputs int + opts []opt + expect []int }{ - {"TestCase", true, true}, - {"TestCase", true, true}, - {"TestCase", false, false}, + {"TestCase1", 2, []opt{ + {"push", 1}, + {"push", 2}, + {"push", 3}, + {"push", 4}, + {"push", 5}, + {"popAtStack", 0}, + {"push", 20}, + {"push", 21}, + {"popAtStack", 0}, + {"popAtStack", 2}, + {"pop", 0}, + {"pop", 0}, + {"pop", 0}, + {"pop", 0}, + {"pop", 0}, + }, []int{2, 20, 21, 5, 4, 3, 1, -1}}, } // 开始测试 for i, c := range cases { t.Run(c.name+" "+strconv.Itoa(i), func(t *testing.T) { - got := Solution(c.inputs) + got := Solution(c.inputs, 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", + c.expect, got, c.inputs, c.opts) } }) } } -// 压力测试 +// 压力测试 func BenchmarkSolution(b *testing.B) { } -// 使用案列 +// 使用案列 func ExampleSolution() { }