数据结构设计类问题
摘要
- 最小栈Minimal stack
- 最大栈Maximum stack
- 两个栈实现队列Two stacks implement queues
- 两个队列实现栈Two queues implement the stack
12 · 带最小值操作的栈
设计一个栈,支持 O(1) push, pop, min
和堆的区别是啥?
堆的 pop 是 pop(min)而栈是 pop 栈顶元素
stack 7 8 6 5 9
minS 7 7 6 5 5
type MinStack struct {
stack []int
minStack []int
}
// 构造函数,初始化两个栈
func NewMinStack() *MinStack {
return &MinStack{}
}
// Push 方法,添加元素到栈中,同时更新 minStack 以保存当前最小值
func (ms *MinStack) Push(number int) {
ms.stack = append(ms.stack, number)
if len(ms.minStack) == 0 {
ms.minStack = append(ms.minStack, number)
} else {
min := ms.minStack[len(ms.minStack)-1]
if number < min {
ms.minStack = append(ms.minStack, number)
} else {
ms.minStack = append(ms.minStack, min)
}
}
}
// Pop 方法,移除并返回栈顶元素,同时更新 minStack
func (ms *MinStack) Pop() int {
if len(ms.stack) == 0 {
panic("Stack is empty")
}
ms.minStack = ms.minStack[:len(ms.minStack)-1]
val := ms.stack[len(ms.stack)-1]
ms.stack = ms.stack[:len(ms.stack)-1]
return val
}
// Min 方法,返回当前栈中的最小值
func (ms *MinStack) Min() int {
if len(ms.minStack) == 0 {
panic("Stack is empty")
}
return ms.minStack[len(ms.minStack)-1]
}
可以优化空间
仅在 MinStack 2 为空或新值小于等于当前最小值时推入 MinStack 2
type MinStack2 struct {
stack []int
MinStack2 []int
}
// 构造函数,初始化两个栈
func NewMinStack2() *MinStack2 {
return &MinStack2{}
}
// Push 方法,添加元素到栈中,同时更新 MinStack2 以保存当前最小值
func (ms *MinStack2) Push(number int) {
ms.stack = append(ms.stack, number)
// 仅在 MinStack2 为空或新值小于等于当前最小值时推入 MinStack2
if len(ms.MinStack2) == 0 || number <= ms.MinStack2[len(ms.MinStack2)-1] {
ms.MinStack2 = append(ms.MinStack2, number)
}
}
// Pop 方法,移除并返回栈顶元素,同时更新 MinStack2
func (ms *MinStack2) Pop() int {
if len(ms.stack) == 0 {
panic("Stack is empty")
}
val := ms.stack[len(ms.stack)-1]
ms.stack = ms.stack[:len(ms.stack)-1]
// 仅当栈顶元素等于 MinStack2 栈顶元素时,移除 MinStack2 栈顶
if val == ms.MinStack2[len(ms.MinStack2)-1] {
ms.MinStack2 = ms.MinStack2[:len(ms.MinStack2)-1]
}
return val
}
// Min 方法,返回当前栈中的最小值
func (ms *MinStack2) Min() int {
if len(ms.MinStack2) == 0 {
panic("Stack is empty")
}
return ms.MinStack2[len(ms.MinStack2)-1]
}
859 · 最大栈
实现 push, pop, top, peekMax, popMax
40 · 两个栈实现队列
除了栈以外不能使用其他数据结构
平均时间复杂度O(1),一个元素最多在两个栈中各进出一次
type MyQueue struct {
stack1 []int
stack2 []int
}
// 构造函数,初始化两个栈
func NewMyQueue() *MyQueue {
return &MyQueue{}
}
// 将 stack2 的所有元素移动到 stack1 中
func (q *MyQueue) stack2ToStack1() {
for len(q.stack2) > 0 {
// 从 stack2 弹出元素并压入 stack1
q.stack1 = append(q.stack1, q.stack2[len(q.stack2)-1])
q.stack2 = q.stack2[:len(q.stack2)-1]
}
}
// Push 方法,添加元素到队列末尾
func (q *MyQueue) Push(element int) {
q.stack2 = append(q.stack2, element)
}
// Pop 方法,移除并返回队列头部元素
func (q *MyQueue) Pop() int {
if len(q.stack1) == 0 {
q.stack2ToStack1()
}
if len(q.stack1) == 0 {
panic("Queue is empty")
}
val := q.stack1[len(q.stack1)-1]
q.stack1 = q.stack1[:len(q.stack1)-1]
return val
}
// Top 方法,返回队列头部元素
func (q *MyQueue) Top() int {
if len(q.stack1) == 0 {
q.stack2ToStack1()
}
if len(q.stack1) == 0 {
panic("Queue is empty")
}
return q.stack1[len(q.stack1)-1]
}
40 · 两个队列实现栈
只能使用队列,不能使用其他数据结构
时间复杂度
- push: O(1)
- pop: O(n)
- top: O(n)
type Queue []int
type Stack struct {
queue1 Queue
queue2 Queue
}
// 构造函数,初始化两个队列
func NewStack() *Stack {
return &Stack{}
}
// 将 queue1 中除最后一个元素外的其他元素全部移动到 queue2
func (s *Stack) moveItems() {
for len(s.queue1) > 1 {
s.queue2 = append(s.queue2, s.queue1[0])
s.queue1 = s.queue1[1:]
}
}
// 交换 queue1 和 queue2 的指针
func (s *Stack) swapQueues() {
s.queue1, s.queue2 = s.queue2, s.queue1
}
// Push 方法,向栈中压入一个新元素
func (s *Stack) Push(value int) {
s.queue1 = append(s.queue1, value)
}
// Top 方法,返回栈顶元素
func (s *Stack) Top() int {
if s.IsEmpty() {
panic("Stack is empty")
}
s.moveItems()
item := s.queue1[0]
s.queue1 = s.queue1[1:]
s.swapQueues()
s.queue1 = append(s.queue1, item)
return item
}
// Pop 方法,移除并返回栈顶元素
func (s *Stack) Pop() {
if s.IsEmpty() {
panic("Stack is empty")
}
s.moveItems()
s.queue1 = s.queue1[1:]
s.swapQueues()
}
// IsEmpty 方法,检查栈是否为空
func (s *Stack) IsEmpty() bool {
return len(s.queue1) == 0
}
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。