最小栈、包含min函数的栈:设计支持在常数时间内检索到最小元素的栈
设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
push(x) —— 将元素 x 推入栈中。
pop() —— 删除栈顶的元素。
top() —— 获取栈顶元素。
getMin() —— 检索栈中的最小元素。
示例:
输入:
["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.
该类题目大多可以使用辅助的数据结构来完成。
首先,使用辅助栈:分别定义两个 stack<int>:需要实现的栈结构 st 以及辅助栈 assistSt。对于常规的栈 st,有元素入栈时直接入栈、有元素出栈时直接出栈,需要读取其栈顶元素时直接返回其栈顶元素即可,即实现栈的常规功能;而检索栈内最小值的操作由辅助栈 assistSt 来完成。
assistSt 首先入栈 INT_MAX 以方便后续比较。assistSt 栈顶元素永远存储 st 栈内的最小值。每次有元素 x 入栈时,先比较 assistSt.top() 与 x 的大小关系:若 x 小于 assistSt 栈顶元素,说明当前需要入栈的数值 x 比当前栈内的数值都小,assistSt 入栈 x;若 x 大于 assistSt 栈顶元素,说明当前需要入栈的数值 x 比当前栈内的最小值更大,assistSt 再次入栈之前栈内的最小值。因此,assistSt 栈顶元素总是存放 st 当前栈内的最小值,在相应 min 函数中直接输出 assistSt.top() 即可。
class MinStack {
stack<int> st;
stack<int> assistSt;
public:
/** initialize your data structure here. */
MinStack() {
assistSt.push(INT_MAX);
}
void push(int x) {
st.push(x);
assistSt.push(::min(assistSt.top(), x));
}
void pop() {
st.pop();
assistSt.pop();
}
int top() {
return st.top();
}
int min() {
return assistSt.top();
}
};
其次,不使用辅助栈:定义需要实现的常规栈结构 st, 以及一个辅助整型数字 min_value,用于存放当前栈内最小值。有元素 x 需要入栈时,判断 x 与 min_value 的大小:若 x <= min_value,说明需要入栈的数值比栈内元素都小,那么首先将原来的 min_value 入栈,用于记录最小值更新之前的最小值,再更新 min_value,最后入栈 x; 若 x > min_value,则直接入栈 x 即可。
st 出栈时,如果栈顶元素等于 min_value,说明 栈顶元素 st.top() 为 x < min_value 情况下入栈的元素,那么其下一个元素为记录的之前的 min_value记录,则首先出栈栈顶元素,然后将 min_value 退回到之前的 min_value,再将多存储的 min_value 记录出栈。
class MinStack {
stack<int> st;
int min_value = INT_MAX;
public:
/** initialize your data structure here. */
MinStack() {
}
void push(int x) {
if(x <= min_value){
st.push(min_value);
min_value = x;
}
st.push(x);
}
void pop() {
if(st.top() == min_value){
st.pop();
min_value = st.top();
}
st.pop();
}
int top() {
return st.top();
}
int min() {
return min_value;
}
};