您的位置:首页 > 职场人生

剑指offer——面试题21:包含 min 函数的栈

2017-10-29 11:28 357 查看
题目:定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。

代码

class Solution {
public:
void push(int value) {
dataStack.push(value);
if(minStack.empty() || minStack.top() > value)   // 本题最重要的就是什么时候,将什么数据压入到两个栈中
{
minStack.push(value);
}
else
minStack.push(minStack.top());
}
void pop() {
minStack.pop();
dataStack.pop();

}
int top() {
return dataStack.top();
}
int min() {
return minStack.top();
}
private:
stack<int> dataStack;
stack<int> minStack;
};


分析

      刚拿到这个问题,第一反应可能是,每压入一个数据,就将栈里面的数据进行排序,保证最小的元素位于栈顶,这样,就能够在 O(1)的情况下,得到最小的元素了。但是,这种方法显然改变了数据结构,不能保证最后压入栈的元素能够最先出栈,因为这个数据结构已经不是栈了。

      那么,能不能在栈中添加一个成员变量,每当压入一个新元素时,如果这个新元素比当前最小的元素还要小,那么,就更新最小的元素。但是,如果面试官问你:如果当前最小的元素已经被弹出栈了,我们如何确定下一个最小的元素?分析到这里,我们明白了:仅仅添加一个成员变量来保存最小的变量,是不够的,我们需要构建一个辅助栈,把每次的最小的元素(之前的最小元素和新压入栈的元素的较小值)都压入辅助栈中。

      下面详细分析下这个过程:





      从表中我们可以看出,如果我们每次都把最小的元素压入辅助栈中,那么就能保证辅助栈中的元素一直是最小的元素。当最小的元素被从数据栈中弹出来的时候,同时弹出辅助栈的栈顶元素。此时,辅助栈新的栈顶的元素,就是下一个最小的元素了。

      《剑指offer》中的代码比我上面写的好,好在加了断言 assert(),保证了程序的鲁棒性。代码如下:

#pragma once

#include <stack>
#include <assert.h>

template <typename T> class StackWithMin
{
public:
StackWithMin(void) {}
virtual ~StackWithMin(void) {}

T& top(void);
const T& top(void) const;

void push(const T& value);
void pop(void);

const T& min(void) const;

bool empty() const;
size_t size() const;

private:
std::stack<T> m_data; // 数据栈,存放栈的所有元素
std::stack<T> m_min; // 辅助栈,存放栈的最小元素
};

template <typename T> void StackWithMin<T>::push(const T& value)
{
// 把新元素添加到辅助栈
m_data.push(value);

// 当新元素比之前的最小元素小时,把新元素插入辅助栈里;
// 否则把之前的最小元素重复插入辅助栈里
if(m_min.size() == 0 || value < m_min.top())
m_min.push(value);
else
m_min.push(m_min.top());
}

template <typename T> void StackWithMin<T>::pop()
{
assert(m_data.size() > 0 && m_min.size() > 0);

m_data.pop();
m_min.pop();
}

template <typename T> const T& StackWithMin<T>::min() const
{
assert(m_data.size() > 0 && m_min.size() > 0);

return m_min.top();
}

template <typename T> T& StackWithMin<T>::top()
{
return m_data.top();
}

template <typename T> const T& StackWithMin<T>::top() const
{
return m_data.top();
}

template <typename T> bool StackWithMin<T>::empty() const
{
return m_data.empty();
}

template <typename T> size_t StackWithMin<T>::size() const
{
return m_data.size();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: