常数时间内检索到最小元素的栈
常数时间 O(1) 指的是无论数据量多大,操作的执行时间都保持恒定不变,不会随着输入规模增加而增加。换句话说,不管栈中有 10 个元素还是 10 万个元素,执行某个操作(如获取最小元素)所需的时间都是一样的。
例:
示例: MinStack minStack = new MinStack(); minStack.push(-2); minStack.push(0); minStack.push(-3); minStack.getMin(); --> 返回 -3. minStack.pop(); minStack.top(); --> 返回 0. minStack.getMin(); --> 返回 -2. 提示: pop、top 和 getMin 操作总是在 非空栈 上调用。
题目说明:
一般栈的 pop()
操作会移除栈顶元素,因此直接获取最小元素通常需要遍历整个栈O(n) 时间复杂度)。但是,我们可以通过辅助栈来优化,使 getMin()
操作始终保持 O(1) 复杂度。
核心思路:
-
push(x)
-
把
x
压入主栈stack
。 -
如果
x
小于等于minStack
栈顶元素(或者minStack
为空),也把x
压入minStack
,保证minStack
栈顶始终是当前栈中的最小值。
-
-
pop()
-
从
stack
中弹出元素。 -
如果弹出的元素 恰好是
minStack
栈顶元素(当前最小值),那minStack
也要同步弹出,保证minStack
仍然正确维护当前最小值。
为什么? 因为minStack
记录的是当前栈中最小的元素,而当stack.pop()
移除的元素正好是最小值时,我们必须同步更新minStack
,否则minStack
可能会存储错误的最小值。
-
-
getMin()
-
直接返回
minStack
栈顶元素即可,时间复杂度 O(1)。
-
代码实现:
1 const stack = { 2 mainStack:[], 3 minStack: [], 4 push(x){ 5 this.mainStack.push(x); 6 const len = this.minStack.length; 7 if(len === 0 || x < this.minStack[len - 1]){ 8 this.minStack.push(x); 9 } 10 }, 11 pop(){ 12 if (this.mainStack.length === 0) return; 13 const lastNum = this.mainStack.pop(); 14 if(lastNum === this.minStack[this.minStack.length -1]){ 15 this.minStack.pop(); 16 } 17 }, 18 getMin(){ 19 return this.minStack[this.minStack.length -1]; 20 } 21 } 22 stack.push(5); 23 stack.push(3); 24 stack.push(7); 25 console.log(stack.getMin()); // 输出 3 26 stack.pop(); 27 console.log(stack.getMin()); // 仍然是 3 28 stack.pop(); 29 console.log(stack.getMin()); // 输出 5