Go猜想录
大道至简,悟者天成
数据结构设计类问题

摘要

  • 最小栈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 国际许可协议进行许可。