设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
实现 MinStack 类:
MinStack()初始化堆栈对象。void push(int val)将元素val推入堆栈。void pop()删除堆栈顶部的元素。int top()获取堆栈顶部的元素。int getMin()获取堆栈中的最小元素。
示例 1:
输入:
["MinStack","push","push","push","getMin","pop","top","getMin"]
[[],[-2],[0],[-3],[],[],[],[]]
输出:
[null,null,null,null,-3,null,0,-2]
解释:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.getMin(); --> 返回 -2.
提示:
-231 <= val <= 231 - 1pop、top和getMin操作总是在 非空栈 上调用push,pop,top, andgetMin最多被调用3 * 104次
1. 脑洞生活案例:你的“前任打分笔记”
想象你是一个记性不太好,但非常严谨的人。你每谈一个新对象,都会在笔记本上记录他们的长相分数。
- 普通记事本(普通栈): 你按顺序记录:8分、6分、9分、5分。
- 你的核心需求: 任何时候,如果闺蜜问你:“你谈过的所有对象里,最丑的一个是多少分? ” 你必须秒回,不能翻书找半天。
你的绝招: 你除了带个**“记录本” ,手里还攥着一个“扎心小纸条”**。
- 第一个对象 8 分:本子上记 8,小纸条写上 8(目前最差)。
- 第二个对象 6 分:本子上记 6。比纸条上的 8 还丑?赶紧在纸条上叠写一个 6。
- 第三个对象 9 分:本子上记 9。没纸条上的 6 丑?别理它,纸条上再写一个 6(为了保持同步,防止分手时乱套)。
- 第四个对象 5 分:本子上记 5。比 6 还丑!纸条上赶紧写个 5。
当分手(Pop)时: 如果你和最后一个(5分那个)分手了,你就把本子最后一页撕了,同时把纸条最上面那个 5 也撕了。 结果: 纸条露出来的最上面那个数字,永远是剩下的人里最丑的!
2. 代码实现(JavaScript)
在代码里,我们就准备两个数组:一个存所有数据(本子),一个存当前最小值(扎心小纸条)。
JavaScript
var MinStack = function() {
this.stack = []; // 普通本子:记录所有人
this.minStack = []; // 扎心小纸条:记录历史最丑
};
/** * @param {number} val
* @return {void}
*/
MinStack.prototype.push = function(val) {
this.stack.push(val);
// 如果小纸条是空的,或者新来的比纸条上最上面的还丑(更小)
// 我们就在纸条上记下这个新的最小值;否则,就把旧的最小值再复制一遍顶上去
if (this.minStack.length === 0 || val <= this.getMin()) {
this.minStack.push(val);
} else {
this.minStack.push(this.getMin());
}
};
/**
* @return {void}
*/
MinStack.prototype.pop = function() {
this.stack.pop();
this.minStack.pop(); // 两个本子同步撕掉,保证一一对应
};
/**
* @return {number}
*/
MinStack.prototype.top = function() {
return this.stack[this.stack.length - 1];
};
/**
* @return {number}
*/
MinStack.prototype.getMin = function() {
return this.minStack[this.minStack.length - 1];
};
3. 方法回顾
这个解法的核心在于:空间换时间。
- 为什么要两个栈? 如果你只用一个变量存最小值,万一那个最小值被
pop掉了,你就不知道第二小的是谁了。 - 同步逻辑: 这就好比影分身。主身(
stack)去闯荡江湖,影子(minStack)专门负责帮他记着“截止到目前为止,你见过最怂的时刻”。主身消失一秒,影子也跟着消失一秒。