题目描述:
用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