目标:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 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.length 16 } 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 < min_stack.top()) { 14 min_stack.push(val) 15 } else { 16 min_stack.push(min_stack.top()) 17 } 18 } 19 pop() { 20 this.data_stack.pop() 21 this.min_stack.pop() 22 } 23 min() { 24 return this.min_stack.top() 25 } 26 }
测试结果
完整代码如下
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.top()) { 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 = new MinStack() 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());
@萍2樱释 ღ( ´・ᴗ・` )