这是一道google的面试题。请帮忙定义一个栈,要求添加一个min函数,能够得到栈里的最小元素。要求min, push, pop的时间复杂度都是O(1).
我们可不可以保存一个临时变量,每次入栈的时候拿入栈的元素和当前最小值去做比较,如果比当前的元素小我们就替换。好像目前是工作的,但是再往下想,如果我现在出栈呢?大家知道,栈里肯定有一个相对较小的元素,而此时,我们已经不知道它是多少呢?所以这种方法是不工作的。
继续往下,刚才的思路中,我们如果能保存每一个比较小的元素,而且出栈的时候我们就抹掉它好像就可以了哈。所以大家想到了什么?似乎要使用另外一个栈,保存较小的元素。那我们一起看下这张表,入栈和出栈的过程中,最小值分别是什么?
步骤 | 栈内元素(右边是顶) | 操作 | 当前最小 | 最小元素辅助栈(右边是顶) |
1 | 4 | 入栈4 | 4 | 4 |
2 | 4,1 | 入栈1 | 1 | 4,1 |
3 | 4,1,5 | 入栈5 | 1 | 4,1 |
4 | 4,1 | 出栈5 | 1 | 4,1 |
5 | 4 | 出栈1 | 4 | 4 |
6 | 4,0 | 入栈0 | 0 | 4,0 |
7 | 4, 0, -2 | 入栈-2 | -2 | 4, 0, -2 |
所以,大家发现没有:
入栈:我们需要拿当前元素和辅助栈的顶端元素比较,如果当前值更小(或相等),我们就入辅助栈,否则不操作
出栈:如果当前出栈的元素和辅助栈的顶端元素比较,如果相等,我们辅助栈也出栈,否则不操作
取最小:我们不需要出栈,直接返回它的值
好了,我们就用一个列表来实现这个栈吧,第一个元素表示栈底,最后一个元素是栈顶哈。一起看代码(当然我们还可以用其他的等多基础结构定义栈哈):
public class MyStack
{
private List<int> stackList = new List<int>();
private List<int> helpStack = new List<int>();
public int Min()
{
if (helpStack.Count > 0)
{
return helpStack.Last();
}
throw new IndexOutOfRangeException();
}
public void Push(int e)
{
stackList.Add(e);
if (helpStack.Count == 0 || (helpStack.Count > 0 && helpStack.Last() >= e))
{
helpStack.Add(e);
}
}
public int Pop()
{
if (stackList.Count > 0)
{
int e = stackList.Last();
stackList.RemoveAt(stackList.Count - 1);
if (helpStack.Count > 0 && helpStack.Last() == e)
{
helpStack.RemoveAt(helpStack.Count - 1);
}
return e;
}
throw new IndexOutOfRangeException();
}
}
好了,大家如果有更好的解法,欢迎提出来我们一起讨论哈。也欢迎大家关注我们的视频教程。
关注我们的公众号,加入QQ群讨论:
![](https://i-blog.csdnimg.cn/blog_migrate/1ccc57424addeadd0e376d9b0a10b4c0.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/d800e3947796507803c0536f6b0dd651.png)