2.5python用O(1)的时间复杂度求栈中最小元素

题目描述:

用O(1)的时间复杂度求栈中最小元素

思路:

由于栈具有后进先出的特点,所以push和pop只能对栈顶元素进行操作,所以如果要使用push或pop来处理的话,只能处理到栈顶元素,无法的到栈中最小的元素。
可以用一个变量来记录栈底的位置,通过遍历栈中所有的元素找到栈中最小的元素,但是遍历所有元素的时间复杂度为O(n)。
在算法设计中,经常采用空间换取时间的方式来降低时间复杂度,也就是采用额外的空间来降低操作的时间复杂度。具体而言,在实现的时候使用两个栈结构,一个栈用来存储数据,另一个栈用来存储栈的最小的元素。
实现思路:
即查找栈中最小元素的时候,操作的时间复杂度为O(1)(存储在栈顶,找的时候直接从栈顶取出来)
如果当前入栈( 代码中的 elemStack )的元素比原来栈中的最小值(存储在minsStack 的栈顶)还小,则把这个值压入保存最小元素的栈( minsStack )中;在出栈( elemStack )的时候,如果出栈的元素恰好为当前栈中的最小值( minsStack 的栈顶元素),保存最小值的栈顶元素也出栈,使得当前最小值变为当前最小值入栈之前的那个最小值。

算法性能分析:
这种方法申请了额外的一个栈空间来保存栈中的最小元素,从而达到了O(1)的时间复杂度;
空间复杂度为O(n);

代码实现:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time    : 2020/1/21 16:49
# @Author  : buu
# @Software: PyCharm
# @Blog    :https://blog.csdn.net/weixin_44321080
class Stack:  # 新建一个栈类
    def __init__(self):  # 模拟栈
        self.items = []  # 用列表实现

    def isEmpty(self):  # 栈是否为空
        return len(self.items) == 0

    def size(self):  # 栈的大小
        return len(self.items)

    def peek(self):  # 取栈顶元素
        if not self.isEmpty():
            return self.items[len(self.items) - 1]
        else:
            return None

    def pop(self):  # 弹栈
        if len(self.items) > 0:  # 先判断栈是否为空
            return self.items.pop()
        else:
            print('stack is empty!')
            return None

    def push(self, item):  # 入栈
        self.items.append(item)


class MyStack():
    def __init__(self):
        self.elemStack = Stack()  # 用来存储栈中元素
        self.minsStack = Stack()  # 栈顶永远存储当前 elemStack 中最小的值

    def push(self, data):  # 更新保存最小元素的栈 minsStack
        """
        如果当前入栈( 代码中的 elemStack )的元素比原来栈中的最小值(存储在minsStack 的栈顶)还小,
        则把这个值压入保存最小元素的栈( minsStack )中
        :param data:
        :return:
        """
        self.elemStack.push(data)
        if self.minsStack.isEmpty():
            self.minsStack.push(data)
        elif data < self.minsStack.peek():
            self.minsStack.push(data)  # 栈顶永远为 elemStack 中的最小值

    def pop(self):
        """
        在出栈( elemStack )的时候,如果出栈的元素恰好为当前栈中的最小值( minsStack 的栈顶元素),
        保存最小值的栈顶元素也出栈,使得当前最小值变为当前最小值入栈之前的那个最小值
        :return:
        """
        topData = self.elemStack.peek()
        self.elemStack.pop()
        if topData == self.mins():
            self.minsStack.pop()
        return topData

    def mins(self):  # minsStack 顶部永远存储栈的最小元素
        if self.minsStack.isEmpty():
            return 2 ** 32
        else:
            return self.minsStack.peek()


if __name__ == '__main__':
    mystack = MyStack()
    mystack.push(5)
    print('min element is: ', mystack.mins())
    mystack.push(6)
    print('min element is: ', mystack.mins())
    mystack.push(2)
    print('min element is: ', mystack.mins())
    mystack.pop()
    print('min element is: ', mystack.mins())

结果:
在这里插入图片描述

end

发布了76 篇原创文章 · 获赞 2 · 访问量 2567

猜你喜欢

转载自blog.csdn.net/weixin_44321080/article/details/104063482