设计一个支持 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 - 1
pop
、top
和getMin
操作总是在 非空栈 上调用push
,pop
,top
, andgetMin
最多被调用3 * 104
次
步骤1:问题定义
输入输出条件:
MinStack()
:初始化一个最小栈对象,无输入,返回一个最小栈对象。push(int val)
:将一个整数val
推入栈中,无返回值。pop()
:从栈中删除顶部的元素,无返回值。top()
:获取栈顶部的元素,返回栈顶的整数。getMin()
:获取栈中的最小元素,返回栈中的最小整数。
限制条件:
- 栈的操作
push
、pop
、top
和getMin
都应在非空栈上调用。 - 栈中元素的范围是
[-2^31, 2^31 - 1]
。 - 栈的操作最多被调用
3 * 10^4
次。
潜在的边界条件:
- 当栈为空时,不能调用
pop
、top
和getMin
。 - 在进行
push
操作时,可能需要更新最小值。
步骤2:解题步骤
解决方案:
- 使用两个栈,一个栈
dataStack
用来存储所有元素,另一个栈minStack
用来存储当前的最小元素。 push
操作:将元素推入dataStack
,如果minStack
为空或minStack
的顶部元素大于等于val
,则将val
也推入minStack
。pop
操作:从dataStack
弹出元素,如果弹出的元素等于minStack
的顶部元素,则也从minStack
弹出。top
操作:返回dataStack
的顶部元素。getMin
操作:返回minStack
的顶部元素。
算法设计思路:
- 使用辅助栈
minStack
来跟踪最小元素,确保getMin
操作的时间复杂度为 O(1)。
时间复杂度:
push
、pop
、top
和getMin
操作的时间复杂度均为 O(1)。
空间复杂度:
- 空间复杂度为 O(n),其中 n 是栈中元素的数量,因为需要额外的空间来存储
minStack
。
步骤3:C++ 代码实现
步骤4:启发
- 在设计数据结构时,可以通过增加额外的空间来优化时间效率。
- 在实现时,应确保所有的操作都能在常数时间内完成,以适应频繁调用的情况。
步骤5:实际应用
应用场景:浏览器历史记录管理
- 浏览器的历史记录可以看作一个栈,用户每次访问新的网页相当于一次
push
操作。 - 当用户点击后退按钮时,相当于执行
pop
操作。 - 如果需要找到历史记录中的最小访问时间(比如找到最早访问的页面),可以使用
getMin
操作。
具体实现:
- 在浏览器的历史记录管理系统中,
MinStack
可以用来存储历史记录和时间戳。 - 每次用户访问新页面时,
push
操作将页面和时间戳推入栈中。 - 如果需要找到最早访问的页面,可以直接调用
getMin
来获取最小时间戳对应的页面。