js_algorithm icon indicating copy to clipboard operation
js_algorithm copied to clipboard

最小栈

Open Cosen95 opened this issue 4 years ago • 1 comments

leetcode: https://leetcode-cn.com/problems/min-stack/

Cosen95 avatar May 09 '20 08:05 Cosen95

这道题目中,其中前三个操作:pushpoptop,数组本身已经提供,我们需要关心的是getMin ,也就是检索栈中的最小元素。

我们很快能想到的一种思路是:初始化一个最小值变量,它的初始值可以设一个非常大的数(比如 Infinity),然后开始遍历整个栈。在遍历的过程中,如果遇到了更小的值,就把最小值变量更新为这个更小的值。这样遍历结束后,我们就能拿到栈中的最小值了。

对应编码实现:

/**
 * initialize your data structure here.
 */
var MinStack = function() {
    // 初始化栈
    this.stack = []
};

/** 
 * @param {number} x
 * @return {void}
 */
MinStack.prototype.push = function(x) {
    this.stack.push(x)
};

/**
 * @return {void}
 */
MinStack.prototype.pop = function() {
    this.stack.pop()
};

/**
 * @return {number}
 */
MinStack.prototype.top = function() {
    if(!this.stack || !this.stack.length) {
        return
    }
    return this.stack[this.stack.length - 1]
};

/**
 * @return {number}
 */
MinStack.prototype.getMin = function() {
    let min = Infinity;
    const { stack } = this;
    for(let i = 0;i < stack.length;i++) {
        if(stack[i] < min) {
            min = stack[i]
        }
    }
    return min
};

/**
 * Your MinStack object will be instantiated and called as such:
 * var obj = new MinStack()
 * obj.push(x)
 * obj.pop()
 * var param_3 = obj.top()
 * var param_4 = obj.getMin()
 */

这个过程中,我们对栈进行了一次遍历,时间复杂度无疑是 O(n)

有没有更好的方案呢?

改善时间复杂度的一个很重要的策略就是时间换空间

我们可以考虑再搞个栈(stack2)出来作为辅助,让这个栈去容纳当前的最小值。

如何确保 stack2 能够确切地给我们提供最小值? 这里我们需要实现的是一个从栈底到栈顶呈递减趋势的栈

  • 取最小值:由于整个栈从栈底到栈顶递减,因此栈顶元素就是最小元素。
  • 若有新元素入栈:判断是不是比栈顶元素还要小,否则不准进入 stack2
  • 若有元素出栈:判断是不是和栈顶元素相等,如果是的话,stack2 也要出栈。

按照这个思路,我们可以有以下编码:

/**
 * initialize your data structure here.
 */
var MinStack = function() {
    // 初始化栈
    this.stack = [];
    this.stack2 = [];
};

/** 
 * @param {number} x
 * @return {void}
 */
MinStack.prototype.push = function(x) {
    this.stack.push(x);
    // stack2 从栈底到栈顶递减 判断当前新增元素小于等于stack2中的最小元素 才可以入栈
    if(this.stack2.length === 0 || this.stack2[this.stack2.length - 1] >= x) {
        this.stack2.push(x)
    }
};

/**
 * @return {void}
 */
MinStack.prototype.pop = function() {
    if(this.stack.pop() === this.stack2[this.stack2.length - 1]) {
        this.stack2.pop()
    }

};

/**
 * @return {number}
 */
MinStack.prototype.top = function() {
    if(!this.stack || !this.stack.length) {
        return
    }
    return this.stack[this.stack.length - 1]
};

/**
 * @return {number}
 */
MinStack.prototype.getMin = function() {
    return this.stack2[this.stack2.length - 1]
};

/**
 * Your MinStack object will be instantiated and called as such:
 * var obj = new MinStack()
 * obj.push(x)
 * obj.pop()
 * var param_3 = obj.top()
 * var param_4 = obj.getMin()
 */

Cosen95 avatar May 09 '20 09:05 Cosen95