剑指 Offer 30. 包含 min 函数的栈 & C++stack & python stack

题目:

定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。

示例:

MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.min();   --> 返回 -3.
minStack.pop();
minStack.top();      --> 返回 0.
minStack.min();   --> 返回 -2.

提示:

    各函数的调用总次数不超过 20000 次

作者:Krahets
链接:https://leetcode-cn.com/leetbook/read/illustration-of-algorithm/50bp33/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

思路:

 

解题思路:

普通栈的 push() 和 pop() 函数的复杂度为 O(1);而获取栈最小值 min() 函数需要遍历整个栈,复杂度为 O(N) 。

本题难点: 将 min() 函数复杂度降为 O(1) 。可借助辅助栈实现:

    数据栈 A : 栈 A 用于存储所有元素,保证入栈 push() 函数、出栈 pop() 函数、获取栈顶 top() 函数的正常逻辑。
    辅助栈 B : 栈 B 中存储栈 A 中所有 非严格降序 元素的子序列,则栈 A 中的最小元素始终对应栈 B 的栈顶元素。此时, min() 函数只需返回栈 B 的栈顶元素即可。

因此,只需设法维护好 栈 B 的元素,使其保持是栈 A 的非严格降序元素的子序列,即可实现 min() 函数的 O(1) 复杂度

剑指 Offer 30. 包含 min 函数的栈 & C++stack & python stack_第1张图片

 

采用 “非严格” 降序原因:

在栈 A 具有 重复 最小值元素时,非严格降序可防止栈 B 提前弹出最小值元素,示例如下:

剑指 Offer 30. 包含 min 函数的栈 & C++stack & python stack_第2张图片

详细实现细节见代码备注

参考:https://leetcode-cn.com/leetbook/read/illustration-of-algorithm/50je8m/

拓展:

c++ stack 以及python stack的常见api可参考楼主博客:

https://blog.csdn.net/Happy_Yu_Life/article/details/113788260

https://blog.csdn.net/Happy_Yu_Life/article/details/113782421

本题目用到的c++ api有:

本题用到了三个api: 
stack.empty()    该函数用于测试堆栈是否为空。如果堆栈为空,则该函数返回true,否则返回false。 
stack.top()         该函数用于访问堆栈的顶部元素。该元素起着非常重要的作用,因为所有插入和删除操作都是在顶部元素上执行的 
stack.pop()        该函数用于删除元素,堆栈中的元素从顶部删除。

特别注意:

python list 的pop()会返回当前弹出元素。

c++ stack 的pop()不会返回当前弹出元素

源码:

/*
思路:引入辅助栈的概念,同时维护两个栈,栈a 进行正常操作,栈b为辅助栈,维持非严格递减序列
*/
class MinStack {
private:
  stack stk_a,stk_b;
public:
    /** initialize your data structure here. */
    MinStack() {}
    
    void push(int x) {
        //压入栈考虑两种情况
        //1、辅助栈 是否为空,若为空,同时将元素压入 栈 a 和栈b
        if(stk_b.empty()){
            stk_a.push(x);
            stk_b.push(x);
        }else if (x <= stk_b.top()){
        //2、若辅助栈非空则需判断 当前元素 x 与栈b的栈顶元素关系,若x<= stk_b.top(),则元素同时插入栈a和栈b
            stk_a.push(x);
            stk_b.push(x);
        }else {
            //3、直接入栈a
            stk_a.push(x);
        }
    }
    
    void pop() {
    //判断合法性,栈是否为空
    if(stk_a.empty()){
        return;
    }
    //1、若栈a和栈b,栈顶元素相等,则同时弹出两者栈顶元素
    if(stk_a.top() == stk_b.top()){
        stk_a.pop();
        stk_b.pop();
    }else{
        //2、否则只弹出栈a的栈顶元素
        stk_a.pop();
    }

    }
    
    int top() {
        return stk_a.top();

    }
    
    int min() {
        return stk_b.top();

    }
};

/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack* obj = new MinStack();
 * obj->push(x);
 * obj->pop();
 * int param_3 = obj->top();
 * int param_4 = obj->min();
 */
####python 实现,采用链表模拟栈,思路同c++实现思路
class MinStack:

    def __init__(self):
        """
        initialize your data structure here.
        """
        self.a,self.b =[],[]

    def push(self, x: int) -> None:
        if not self.b or self.b[-1] >= x:
            self.b.append(x)
            self.a.append(x)
        else:
            self.a.append(x)

    def pop(self) -> None:
        ####小技巧,python 的pop()返回对应数值,故可直接弹出栈a,再判断
        if self.a.pop() == self.b[-1]:
            self.b.pop()
    def top(self) -> int:
        return self.a[-1]

    def min(self) -> int:
        return self.b[-1]

 

你可能感兴趣的:(C/C++,日常编程,LeetCode,c++,数据结构,堆栈,算法)