题目
设计一个Stack,实现如下操作:
- push(), 入栈
- pop(), 出栈
- top(), 返回栈顶元素
- getMin(), 返回栈中的最小元素
注意上面的操作,都要在常数时间完成。
分析
Leetcode上面的原题,思路并不难想,但是AC还是有难度的,尤其是用Java,如果能够确保不出现MLE?我们先逐步分析一下。
首先,第一个思路,最容易想到,定义一个新的栈,栈的每一个元素包含两个数,一个当前数,一个入栈到目前为止的最小数。有如下的代码示例:
|
|
代码很简单,但是MLE,内存超了。。。很不幸。那么如何优化呢?其实我们自己走一走这个过程,就会发现,在入栈出栈,以及getMin的过程中,有一些值,是不会出现在getMin中的。有一些min的数都是一样的。
那么我们浪费了空间来存储这些一样的min值,显然是不可以的。我们做如下的优化,用另外一个栈来保存最小值,每一个栈元素除了包括最小值之外,还有一个频率。这样我们压缩了存储最小值的栈。比之前的栈要小很多。
示例代码如下:
|
|
提交之后,你会发现,代码还是有问题,人就是内存不过关,还能怎么优化呢?难道是LinkedList的问题?实际上,还真是这个问题。Java中LinkedList是一个双向的链表,实际上我们实现一个栈,只需要单向的。我们自己实现栈试试。代码比较糙,有些实现也不合规范。
但意思没问题,如下:
|
|
通过了,看来问题确实如此。这也给了我们一个提醒,在实际的编码中,需要考虑的不仅仅是功能的实现,还有效率上的考虑。我们往往优先考虑时间,大多数时间考虑时间。但,空间也是同样重要的,尤其是Java这样的语言。
【完】