牛客网在线编程专题《剑指offer-面试题21》包含min函数的栈

微信公众号

题目链接:

https://www.nowcoder.com/practice/4c776177d2c04c2494f2555c9fcc1e49?tpId=13&tqId=11173&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking

题目描述:

解题思路:

        看到这个问题, 我们的第一反应可能是每次压入一个新元素进栈时, 将栈里的所有元素排序, 让最小的元素位于栈顶, 这样就能在0(1)时间得到最小元素了。 但这种思路不能保证最后压入栈的元素能够最先出栈, 因此这个数据结构已经不是栈了。

        我们接着想到在栈里添加一个成员变量存放最小的元素。 每次压入一个新元素进栈的时候,如果该元素比当前最小的元素还要小,则更新最小元素。 面试官听到这种思路之后就会问: 如果当前最小的元素被弹出栈了, 如何得到下一个最小的元素呢?

        分析到这里我们发现仅仅添加一个成员变量存放最小元素是不够的,也就是说当最小元素被弹出栈的时候, 我们希望能够得到次小元素。 因此在压入这个最小元素之前, 我们要把次小元素保存起来。

        是不是可以把每次的最小元素(之前的最小元素和新压入栈的元素两者的较小值)都保存起来放到另外一个辅助栈里呢?我们不妨举几个例子来分析一下把元素压入或者弹出栈的过程(如表1所示)。
        首先住空的数据栈里压入数字3, 显然现在3是最小值, 我们也把这个最小值压入辅助栈。 接下来往数据栈里压入数字4。 由于4大于之前的最小值, 因此我们仍然往辅助栈里压入数字3。第三步继续往数据栈里压入数字2。由于2 小于之前的最小值 3,因此我们把最小值更新为2,并把2压入辅助栈。同样当压入数字1时,也要更新最小值,并把新的最小值1压入辅助栈。

表1 栈内压入3、4、2、1之后接连两次弹出栈顶数字再压入0时,数据栈、辅助栈和最小值的状态
步骤操作数据栈辅助栈最小值
1压入3333
2压入43、43、33
3压入23、4、23、3、22
4压入13、4、2、13、3、2、11
5弹出3、4、23、3、22
6弹出3、43、33
7压入03、4、03、3、00

       从表1中我们可以看出,如果每次都把最小元素压入辅助栈,那么就能保证辅助栈的栈顶一直都是最小元素。当最小元素从数据栈内被弹出之后, 同时弹出辅助栈的栈顶元素,此时辅助栈的新栈顶元素就是下一个最小值。比如第四步之后,栈内的最小元素是1。当第五步在数据栈内弹出1后,我们把辅助栈的栈顶弹出, 辅助栈的栈顶元素2就是新的最小元素。接下来继续弹出数据栈和辅助栈的栈顶之后,数据栈还剩下 3、4 两个数字,3是最小值。 此时位于辅助栈的栈顶数字正好也是3,的确是最小值。 这说明我们的思路是正确的。

已经AC的代码:

'''
题目:定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。
'''
class Solution:

    def __init__(self):
        self.stack = []
        self.minStack = []
        self.min_num = None

    def push(self, node):
        # write code here
        self.stack.append(node)
        if self.min_num is None:
            self.min_num = node
            self.minStack.append(self.min_num)
        elif self.min_num < node:
            self.minStack.append(self.min_num)
        else:
            self.min_num = node
            self.minStack.append(node)

    def pop(self):
        # write code here
        if len(self.stack) > 0 and len(self.minStack):
            self.minStack.pop()
            self.stack.pop()

    def top(self):
        # write code here
        return

    def min(self):
        # write code here
        return self.minStack[-1]

if __name__ == '__main__':
    stack = Solution()
    current_stack = [11, 7, 8, 9, 5, 12, 15]
    for num in (current_stack):
        stack.push(num)
    print(stack.min(), stack.stack)
    print(stack.minStack)
    # 测试用例
    # 输入一个比最小值大的
    stack.push(7)
    print(stack.min(), stack.stack)

    # 输入一个比最小值小的
    stack.push(4)
    print(stack.min(), stack.stack)

    # 弹出最小值
    stack.pop()
    print(stack.min(), stack.stack)

    # 弹出非最小值
    stack.pop()
    print(stack.min(), stack.stack)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值