题目描述
定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。在该栈中,调用min,push及pop的时间复杂度都是O(1)。
分析:
数组模拟栈可以做到O(1)push和pop,但是只有一个数组的话min还是O(n)级。那么只能在push的时候就记录最小值,但是万一最小值出栈,此时的最小值该怎么办?难道要记录次小值?那次小值在哪,难道还要记录次小值下标········越想越复杂。
关键:
使用辅助栈,每次push一个元素,同时把当前最小值也push进辅助栈;数据栈pop一次辅助栈也pop,这样就可以保证辅助栈栈顶一定是当前最小值。这样的话只需要在push和pop增加相应判断操作,实现起来用stack或者数组模拟都无所谓,都是O(1),某种程度上讲,数组模拟的优势(随机读取)没了。
剑指offer原版代码:
#include <stdio.h>
#include <stdlib.h>
#include <stack>
#include <assert.h>
using namespace std;
template <typename T>
class StackWithMin
{
private:
stack<T> m_stack; //数据栈
stack<T> m_min; //辅助栈
public:
//栈操作
void push(const T& value)
{
if (isEmpty() || value < min())
{
m_stack.push(value);
m_min.push(value);
}
else
{
m_stack.push(value);
m_min.push(min());
}
}
void pop()
{
assert(m_stack.size() > 0 && m_min.size() > 0);
m_stack.pop();
m_min.pop();
}
const T& top()
{
return m_stack.top();
}
const T& min()
{
assert(m_stack.size() > 0 && m_min.size() > 0);
return m_min.top();
}
bool isEmpty()
{
return m_stack.size() == 0;
}
};
int main()
{
StackWithMin<int> st;
int number = 0;
while (scanf("%d", &number) != EOF)
{
st.push(number);
printf("最小值:%d\n", st.min());
}
int i = 1;
while (!st.isEmpty())
{
printf("pop %d次,最小值:%d\n", i++, st.min());
st.pop();
}
getchar();
return 0;
}