题目
设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
push(x) —— 将元素 x 推入栈中。
pop() —— 删除栈顶的元素。
top() —— 获取栈顶元素。
getMin() —— 检索栈中的最小元素。
示例:
输入:
[“MinStack”,“push”,“push”,“push”,“getMin”,“pop”,“top”,“getMin”]
[[],[-2],[0],[-3],[],[],[],[]]
输出:
[null,null,null,null,-3,null,0,-2]
分析
最小栈,如果只使用一个的话,那么是没法记录最下的元素,如果在push的时候,比较记录最小值,那也只能记录一个最小值,但这个元素被删除时候,就需要遍历计算了,所以这样的方法不可取。
**我们需要一个当删除一个最小值时,我们还有一个次最小值,然后继续pop元素时候,当次最小值也被pop出去的时候,我们还有一个次次最小值。**即我们希望有一个数据结构,能够存储类似第一最小值,第二最小值,第三最小值,,,,,
,在这里想到了栈,它还能实现O(1)返回最小值。我们用一个辅助栈,存储这个当前的最小值,这样每次push的时候,我们发现它比之前的最小值小,那么就将它push到铺助栈中,如果我们遇到比当前栈辅助栈栈顶元素大,就不需要考虑。这里注意如果push的元素恰好等于辅助栈栈顶元素,那么也是需要push进去的,否则pop出相同大小元素时候,会把最小栈给pop没了。
解法
type MinStack struct {
stack []int
minstack []int
}
/** initialize your data structure here. */
func Constructor() MinStack {
return MinStack{
}
}
func (this *MinStack) Push(x int) {
if len(this.stack) == 0{
this.minstack = append(this.minstack, x)
} else {
// 只有比辅助栈的栈顶元素小,就需要入栈,一样大的也需要入栈,因为出栈的时候,如果遇到一样大的,就出了,回有两边不同步的问题
minLen := len(this.minstack)
if x <= this.minstack[minLen-1] {
this.minstack = append(this.minstack, x)
}
}
this.stack = append(this.stack, x)
// fmt.Printf("push %d into %v \n", x, this.stack)
// fmt.Printf("minstack: %v\n", this.minstack)
}
func (this *MinStack) Pop() {
length := len(this.stack)
if length == 0 {
return
}
minLen := len(this.minstack)
if this.stack[length-1] == this.minstack[minLen-1] {
this.minstack = this.minstack[:minLen-1]
}
this.stack = this.stack[:length-1]
}
func (this *MinStack) Top() int {
length := len(this.stack)
if length == 0 {
return -1
}
return this.stack[length-1]
}
func (this *MinStack) GetMin() int {
if len(this.stack) == 0 {
return -1
}
return this.minstack[len(this.minstack)-1]
}
/**
* Your MinStack object will be instantiated and called as such:
* obj := Constructor();
* obj.Push(x);
* obj.Pop();
* param_3 := obj.Top();
* param_4 := obj.GetMin();
*/