题目:
定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。
示例:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.min(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.min(); --> 返回 -2.提示:
各函数的调用总次数不超过 20000 次
作者:Krahets
链接:https://leetcode-cn.com/leetbook/read/illustration-of-algorithm/50bp33/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
思路:
解题思路:
普通栈的 push() 和 pop() 函数的复杂度为 O(1);而获取栈最小值 min() 函数需要遍历整个栈,复杂度为 O(N) 。
本题难点: 将 min() 函数复杂度降为 O(1) 。可借助辅助栈实现:
数据栈 A : 栈 A 用于存储所有元素,保证入栈 push() 函数、出栈 pop() 函数、获取栈顶 top() 函数的正常逻辑。
辅助栈 B : 栈 B 中存储栈 A 中所有 非严格降序 元素的子序列,则栈 A 中的最小元素始终对应栈 B 的栈顶元素。此时, min() 函数只需返回栈 B 的栈顶元素即可。因此,只需设法维护好 栈 B 的元素,使其保持是栈 A 的非严格降序元素的子序列,即可实现 min() 函数的 O(1) 复杂度
采用 “非严格” 降序原因:
在栈
A
具有 重复 最小值元素时,非严格降序可防止栈B
提前弹出最小值元素,示例如下:详细实现细节见代码备注
参考:https://leetcode-cn.com/leetbook/read/illustration-of-algorithm/50je8m/
拓展:
c++ stack 以及python stack的常见api可参考楼主博客:
https://blog.csdn.net/Happy_Yu_Life/article/details/113788260
https://blog.csdn.net/Happy_Yu_Life/article/details/113782421
本题目用到的c++ api有:
本题用到了三个api: stack.empty() 该函数用于测试堆栈是否为空。如果堆栈为空,则该函数返回true,否则返回false。 stack.top() 该函数用于访问堆栈的顶部元素。该元素起着非常重要的作用,因为所有插入和删除操作都是在顶部元素上执行的 stack.pop() 该函数用于删除元素,堆栈中的元素从顶部删除。
特别注意:
python list 的pop()会返回当前弹出元素。
c++ stack 的pop()不会返回当前弹出元素
源码:
/*
思路:引入辅助栈的概念,同时维护两个栈,栈a 进行正常操作,栈b为辅助栈,维持非严格递减序列
*/
class MinStack {
private:
stack<int> stk_a,stk_b;
public:
/** initialize your data structure here. */
MinStack() {}
void push(int x) {
//压入栈考虑两种情况
//1、辅助栈 是否为空,若为空,同时将元素压入 栈 a 和栈b
if(stk_b.empty()){
stk_a.push(x);
stk_b.push(x);
}else if (x <= stk_b.top()){
//2、若辅助栈非空则需判断 当前元素 x 与栈b的栈顶元素关系,若x<= stk_b.top(),则元素同时插入栈a和栈b
stk_a.push(x);
stk_b.push(x);
}else {
//3、直接入栈a
stk_a.push(x);
}
}
void pop() {
//判断合法性,栈是否为空
if(stk_a.empty()){
return;
}
//1、若栈a和栈b,栈顶元素相等,则同时弹出两者栈顶元素
if(stk_a.top() == stk_b.top()){
stk_a.pop();
stk_b.pop();
}else{
//2、否则只弹出栈a的栈顶元素
stk_a.pop();
}
}
int top() {
return stk_a.top();
}
int min() {
return stk_b.top();
}
};
/**
* Your MinStack object will be instantiated and called as such:
* MinStack* obj = new MinStack();
* obj->push(x);
* obj->pop();
* int param_3 = obj->top();
* int param_4 = obj->min();
*/
####python 实现,采用链表模拟栈,思路同c++实现思路
class MinStack:
def __init__(self):
"""
initialize your data structure here.
"""
self.a,self.b =[],[]
def push(self, x: int) -> None:
if not self.b or self.b[-1] >= x:
self.b.append(x)
self.a.append(x)
else:
self.a.append(x)
def pop(self) -> None:
####小技巧,python 的pop()返回对应数值,故可直接弹出栈a,再判断
if self.a.pop() == self.b[-1]:
self.b.pop()
def top(self) -> int:
return self.a[-1]
def min(self) -> int:
return self.b[-1]