每天学习一点算法 2026/01/06
题目:最小栈
设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
实现 MinStack 类:
MinStack() 初始化堆栈对象。
void push(int val) 将元素val推入堆栈。
void pop() 删除堆栈顶部的元素。
int top() 获取堆栈顶部的元素。
int getMin() 获取堆栈中的最小元素。
这个题目的push、pop、top方法都很简单,主要就在于获取堆栈中的最小元素。
我们先按常规逻辑实现一版:
typescript
class MinStack {
private stack: number[]
constructor() {
this.stack = []
}
push(val: number): void {
this.stack.push(val)
}
pop(): void {
this.stack.length > 0 && this.stack.pop()
}
top(): number | null {
if (this.stack.length === 0) return null
return this.stack[this.stack.length - 1]
}
getMin(): number | null {
if (this.stack.length === 0) return null
return this.stack.reduce((prev, current) => {
return prev === null ? current : Math.min(prev, current)
}, null)
}
}
这样虽然实现了功能但是达不到在常数时间内检索到最小元素的要求。
其实很容易就能想到,所有元素都是通过push方法压入栈中的,我们可以用一个变量存储最小值,每次入栈将入栈值跟最小值作比较就能获取到最小值,但是有一个问题就是,一旦执行了弹栈的操作,我们的最小值就会丢失,所以我们需要用一个辅助栈才存储每个元素入栈时的最小元素,这样就算弹栈之前的最小值也不会丢失。
typescript
class MinStack {
private stack: number[] // minStack
private minHistory: number[] // 最小值历史
constructor() {
// 初始化最小值栈和辅助栈
this.stack = []
this.minHistory = []
}
push(val: number): void {
const prevMin = this.minHistory[this.minHistory.length - 1] // 取出上一次入栈时的最小值
if (prevMin === undefined) this.minHistory.push(val) // 栈为空时,val就是最小值
else this.minHistory.push(Math.min(val, prevMin)) // 栈非空,存储最新的最小值
this.stack.push(val) // 元素压栈
}
pop(): void {
this.stack.length > 0 && this.stack.pop() // 元素弹栈
this.minHistory.length > 0 && this.minHistory.pop() // 最小值历史弹栈
}
top(): number | undefined {
return this.stack[this.stack.length - 1]
}
getMin(): number | undefined {
return this.minHistory[this.minHistory.length - 1] // 返回最小值历史栈顶
}
}
题目来源:力扣(LeetCode)