题目描述:
Design a stack that supports push, pop, top, and retrieving the
minimum element in constant time.
要实现的栈方法
push(x) – Push element x onto stack.
pop() – Removes the element on top of the stack.
top() – Get the top element.
getMin() – Retrieve the minimum element in the stack.
两种解法
方法一
先想到的第一种方法如下:
- 用一个数组保存数据
push
、pop
、top
方法都唾手可得getMin
方法要获取最小值,就遍历数组,找到最小值并返回
由于 getMin
方法中的一次 for 循环,时间复杂度为 O(n)。
这里存在优化的空间。
var MinStack = function () {
this.stack = []
}
MinStack.prototype.push = function (x) {
this.stack.push(x)
}
MinStack.prototype.pop = function () {
this.stack.pop()
}
MinStack.prototype.top = function () {
let len = this.stack.length
if (len > 0) {
return this.stack[len - 1]
}
}
MinStack.prototype.getMin = function () {
let stack = this.stack
let tempMin = stack[0]
for (let i = 1; i < stack.length; i++) {
if (tempMin > stack[i]) {
tempMin = stack[i]
}
}
return tempMin
}
方法二
核心思路:
用另一个数组保存每个新元素入栈时,当时的最小值。
push
pop
方法中多维护一个 min 数组getMin
时,只需要取 min 数组最后一位即可- 由于省去了 for 循环,时间复杂度将为常数阶 O(1)
照这个思路有了第一版代码如下
var MinStack = function () {
this.stack = []
this.min = []
}
MinStack.prototype.push = function (x) {
this.stack.push(x)
let min = this.min[this.min.length - 1]
if (min !== undefined) {
min > x ? this.min.push(x) : this.min.push(min)
} else {
this.min.push(x)
}
}
MinStack.prototype.pop = function () {
this.stack.pop()
this.min.pop()
}
MinStack.prototype.top = function () {
let len = this.stack.length
if (len > 0) {
return this.stack[len - 1]
}
}
MinStack.prototype.getMin = function () {
let len = this.min.length
if (len > 0) {
return this.min[len - 1]
}
}
容易发现,push
方法中,取得之前最小值的操作与 getMin
方法存在重复,本着 DRY (do not repeat youself)的原则,修改 push
如下
方法二代码
var MinStack = function () {
this.stack = []
this.min = []
}
MinStack.prototype.push = function (x) {
let preMin = this.getMin()
if (preMin !== undefined) {
preMin > x ? this.min.push(x) : this.min.push(preMin)
} else {
this.min.push(x)
}
this.stack.push(x)
}
MinStack.prototype.pop = function () {
this.stack.pop()
this.min.pop()
}
MinStack.prototype.top = function () {
let len = this.stack.length
if (len > 0) {
return this.stack[len - 1]
}
}
MinStack.prototype.getMin = function () {
let len = this.min.length
if (len > 0) {
return this.min[len - 1]
}
}
性能对比
两种方法运行时间对比如下(JavaScript),可见速度有了明显提升。
对应的 Python 描述如下
方法一
class MinStack(object):
def __init__(self):
"""
initialize your data structure here.
"""
self.stack = []
def push(self, x):
"""
:type x: int
:rtype: void
"""
self.stack.append(x)
def pop(self):
"""
:rtype: void
"""
self.stack.pop()
def top(self):
"""
:rtype: int
"""
return self.stack[-1]
def getMin(self):
"""
:rtype: int
"""
return min(self.stack)
方法二
class MinStack(object):
def __init__(self):
"""
initialize your data structure here.
"""
self.stack = []
self.min = []
def push(self, x):
"""
:type x: int
:rtype: void
"""
self.stack.append(x)
if(len(self.min) > 0):
self.min.append(min([x, self.min[-1]]))
else:
self.min.append(x)
def pop(self):
"""
:rtype: void
"""
self.stack.pop()
self.min.pop()
def top(self):
"""
:rtype: int
"""
return self.stack[-1]
def getMin(self):
"""
:rtype: int
"""
return self.min[-1]