目标:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。
设计思路: 我们要做的是在我们每次数据入栈的时候,记录当前数据栈中最小值,并且在pop()出栈之后依然能找到最小值;
方案①,如果只用一个 min 变量来保存每次入栈时候的最小值,那么出栈的时候,当前的最小值还是栈中的最小值吗?假设栈中的数据按入栈顺序依次为[ 2, 3, 5, 1 ] ,很明显此时记录的min值为1,那么当我们pop()出一条数据之后,堆栈变为 [ 2, 3, 5 ] ,此时的最小值应为2,但是记录的min值为1,最小值记录已丢失,此方案不通。
方案②,基于方案①的问题,我们应该设计一个结构,能够保存我们每一步入栈的时候情况下的当前最小值。可能我们会想到用数组结构排序后取最小值,但是要保证时间复杂度为O(1),那么数组结构方案舍弃(没有一种数组排序为O(1)复杂度)。
方案③,在这里我采用堆栈结构来保存记录最小值,为什么采用堆栈呢,堆栈结构有一个特点是保护现场和恢复现场的功能。想象一下,每次我们数据入栈时保存最小值,出栈的时候还要能恢复上一次的最小值,是不是和堆栈的这个特点不谋而合呢。所以我们采用堆栈结构。当然,在这里我们需要使用双倍的存储空间来实现功能,以空间换取时间╮(╯▽╰)╭。
首先我们实现一个Stack结构,代码如下:
1 class Stack {2 constructor() {3 this.stack =[]4 }5 push(v) {6 this.stack.push(v)7 }8 pop() {9 this.stack.pop()10 }11 isEmpty() {12 return !this.count()13 }14 count() {15 return this.stack.length16 }17 top() {18 return this.stack[this.count() - 1]19 }20 }
接着实现最小堆栈代码
1 class MinStack {2 data_stack = new Stack() //存放真正的栈数据
3 min_stack = new Stack() //存放最小值栈
4 constructor() { }5 push(val) {6 const min_stack = this.min_stack;7 //数据入栈
8 this.data_stack.push(val);9 /*在最小堆栈中记录每一次更新堆栈的当前情况下的最小值,10 即保证最小栈栈顶始终记录的是当前数据栈中最小的那个值,11 那么在每次pop的时候,最小栈栈顶记录的依旧记录的是最小值,12 就不用担心第二小值的问题啦*/
13 if (min_stack.isEmpty() || val
测试结果
完整代码如下
class Stack {
constructor() {this.stack =[]
}
push(v) {this.stack.push(v)
}
pop() {this.stack.pop()
}
isEmpty() {return !this.count()
}
count() {return this.stack.length
}
top() {return this.stack[this.count() - 1]
}
}
class MinStack {
data_stack= new Stack() //存放真正的栈数据
min_stack = new Stack() //存放最小值栈
constructor() { }
push(val) {
const min_stack= this.min_stack;//数据入栈
this.data_stack.push(val);/*在最小堆栈中记录每一次更新堆栈的当前情况下的最小值,
即保证最小栈栈顶始终记录的是当前数据栈中最小的那个值,
那么在每次pop的时候,最小栈栈顶记录的依旧记录的是最小值,
就不用担心第二小值的问题啦*/
if (min_stack.isEmpty() || val
min_stack.push(val)
}else{
min_stack.push(min_stack.top())
}
}
pop() {this.data_stack.pop()this.min_stack.pop()
}
min() {return this.min_stack.top()
}
}
const min_stack= newMinStack()
min_stack.push(2)
console.log(min_stack.min());
min_stack.push(3)
console.log(min_stack.min());
min_stack.push(5)
console.log(min_stack.min());
min_stack.push(1)
console.log(min_stack.min());
min_stack.pop()
console.log(min_stack.min());
MinStack
@