剑指offer系列-面试题30-包含min函数的栈(python)

文章目录

  • 1. 题目
  • 2. 解题思路
    • 2.1 我的思路
    • 2.1 书中的思路
  • 3. 代码实现
  • 4. 总结
  • 5. 参考文献

1. 题目

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

2. 解题思路

栈的特点是后进先出。
push(),将元素压入栈顶
pop(),将元素从栈顶弹出

2.1 我的思路

要得出栈中的最小值,那肯定要遍历这个栈中的所有元素,比较大小,记录最小值,然后返回最小值。要遍历栈,那肯定就要从数据栈中弹出元素,记录大小,然后按照弹出的顺序的逆序再将元素压入栈内。但是这样的算法时间复杂度肯定大于O(1)。

既然时间复杂度要是O(1),根据空间换时间的思想,那肯定是需要额外的空间的。

  1. 首先,想定义一个变量来记录最小元素,当新push()进来的元素小于记录的元素时,修改记录的元素。但是问题是,如果数据栈pop()了这个最小元素的话,此时如何在O(1)时间复杂度内找到剩余栈的最小元素呢?
  2. 使用一个辅助栈,将数据栈中的元素排序好,最小的元素放在栈顶,这样可以实现O(1)时间复杂度内获得最小元素。但是这样做有一个问题就是,push()进来的新元素大于最小元素,那么这个元素在辅助栈中怎么才能放到它对应的位置呢?

2.1 书中的思路

在使用辅助栈的时候有些区别,辅助栈中记录的元素并不是要跟数据栈中的元素都是一致的,辅助栈的作用是记录当前数据栈中的最小值。仔细品品这句话。每次都把最小元素压入辅助栈,那么就能保证辅助栈的栈顶一直都是最小元素。当最小元素从数据栈内被弹出之后,同时弹出辅助栈的栈顶元素,此时辅助栈的新栈顶元素就是下一个最小值。

3. 代码实现

python 实现栈

class Stack(object):
 	# 初始化栈为空列表
	def __init__(self, iterable):
		self.values = []
	# 向栈顶压入一个新数据项
	def push(self, value):
		self.values.append(value)
	# 返回栈顶元素,并删除
	def pop(self):
		reurn self.values.pop()
	# 判断栈是否为空
	def is_empty(self):
        return self.size() == 0
	# 返回栈的大小
    def size(self):
        return len(self.values)
	# 返回栈顶数据项,但不删除。
    def peak(self):
        return self.values[self.size()-1]
	

栈的min函数

class myStack(Stack):
    def __init__(self):
        # 数据栈
        self.data_stack = Stack()
        # 辅助栈
        self.min_stack = Stack()
    
    def push(self, value):
        self.data_stack.push(value)
        # 辅助栈大小<0,或者新压入的值小于辅助栈的栈顶元素,将次元素压入辅助栈顶,否则将当前最小值压入栈顶
        if self.min_stack.size() == 0 or value < self.min_stack.peak():
            self.min_stack.push(value)
        else:
            self.min_stack.push(self.min_stack.peak())
    
    def pop(self):
        if self.data_stack.size() > 0 and self.min_stack.size() > 0:
            res = self.data_stack.pop()
            self.min_stack.pop()
        return res

    # 返回栈的大小
    def size(self):
        return len(self.data_stack.values)

    # 返回栈顶数据项,但不删除。
    def peak(self):
        return self.data_stack.values[self.size()-1]
    
     # 判断栈是否为空
    def is_empty(self):
        return self.size() == 0

    def min(self):
        if self.min_stack.size() > 0:
            return self.min_stack.peak()
    

if __name__ == '__main__':
    my_stack = myStack()
    my_stack.push(3)
    my_stack.push(4)
    my_stack.push(4)
    my_stack.push(2)
    my_stack.push(1)
    my_stack.push(2)

    while my_stack.size() > 0:
        print("当前栈中最小值{}".format(my_stack.min()))
        res = my_stack.pop()
        print("弹出数据栈栈顶元素{}".format(res))
	
	

4. 总结

多举例子,找到规律之后在解决问题。

5. 参考文献

[1] 剑指offer丛书

你可能感兴趣的:(算法)