#!/usr/bin/env python
# encoding: utf-8
'''
Python程序员面试算法宝典---解题总结: 第二章 栈、队列与哈希 2.5 如何用O(1)的时间复杂度求栈中最小元素
分析:
O(1)时间查找到最小的元素最容易实现的方式就是将最小元素始终放在栈顶,
这样每次只需要获取栈顶元素,即可获取最小元素。
那么问题的关键就是如何在压入元素的时候确保最小元素在栈顶。
一种思路就是设置两个栈,对两个栈进行操作。
举例如下: 假设入栈序列为: 5,3,4,2,1
假设有栈1为s1,栈2为s2。
将5压入s1,此时压入3之前,判断s1的栈顶元素为5,此时因为3小于5,就继续把元素3压入到s1中,
此时s1从站顶到栈顶序列如下:
s1 s2
3
5
此时判断4大于s1的栈顶元素3,此时不能插入s1中,此时将
s1中的元素全部压入s2中,直到s1的栈顶元素大于当前待压入元素4,
最后将元素4压入到s2中,此时s1,s2中元素如下:
s1 s2
5 4
3
最后每次取出s2栈顶元素压入s2中,直到s2为空,此时s1,s2如下:
s1 s2
3
4
5
总结:
算法步骤:
步骤1: 若栈s1为空,则将当前待压入元素压入到s1中;
步骤2: 否则,如果s1非空
2.1 如果当前待压入元素小于s1的栈顶元素,则将当前待压入元素,压入到s1中
2.2 2.2.1) 否则,只要当前待压入元素大于s1栈顶元素,就弹出s1栈顶元素并压入到栈s2中;
重复步骤2.2,直到s1为空或者当前待压入元素小于s1栈顶元素;
2.2.2) 最后将当前待压入元素压入到s2中;
2.2.3) 只要s2不空,就将s2的栈顶元素不断弹出并压入到s1中。
通过以上步骤,确保了s1中的栈顶元素始终是最小的元素,即可满足O(1)时间复杂度获取栈中最小元素
弄错了,这个是修改了栈的入栈顺序,弹出栈会出错。
书上的解法:
用另外一个栈记录最小元素。
一个元素栈保存原来的真实入栈序列;用一个min栈,
如果min栈为空,则压入当前待压入元素;
否则,如果当前待压入元素比min栈的栈顶元素小,则将当前
待压入元素压入到min栈中。
出栈的时候,真实入栈序列直接弹出栈顶元素;
对于min栈,如果待弹出元素和min栈栈顶元素相同,则弹出min栈的栈顶元素。
关键:
1 用另外一个栈记录最小元素。
一个元素栈保存原来的真实入栈序列;用一个min栈,
如果min栈为空,则压入当前待压入元素;
否则,如果当前待压入元素比min栈的栈顶元素小,则将当前
待压入元素压入到min栈中。
出栈的时候,真实入栈序列直接弹出栈顶元素;
对于min栈,如果待弹出元素和min栈栈顶元素相同,则弹出min栈的栈顶元素。
2 用两个栈来回倒腾实现的是排序栈的功能
3 记录一个min栈记录最小元素序列即可。
当前待插入元素比min栈的栈顶小就插入到min栈中。
参考:
Python程序员面试算法宝典
'''
class Stack(object):
def __init__(self):
self.data = list()
def empty(self):
result = False if self.data else True
return result
def push(self, data):
self.data.append(data)
def pop(self):
if not self.empty():
self.data.pop()
else:
info = "stack is empty, it can not pop"
print info
def top(self):
if not self.empty():
return self.data[-1]
else:
info = "stack is empty, it can not get top element"
print info
class SortStack(object):
def __init__(self):
self.stack1 = Stack()
self.stack2 = Stack()
def empty(self):
return self.stack1.empty()
def push(self, data):
if not self.empty():
while not self.empty() and self.stack1.top() < data:
top = self.stack1.top()
if top is not None:
self.stack2.push(top)
self.stack1.pop()
self.stack2.push(data)
while not self.stack2.empty():
top = self.stack2.top()
self.stack2.pop()
if top is not None:
self.stack1.push(top)
else:
self.stack1.push(data)
def pop(self):
if not self.empty():
self.stack1.pop()
else:
info = "stack is empty, it can not pop"
print info
def min(self):
if not self.empty():
return self.stack1.top()
else:
info = "stack is empty, it can not get min element"
print info
class MinStack(object):
def __init__(self):
self.elementStack = Stack()
self.minStack = Stack()
def empty(self):
return self.elementStack.empty()
def push(self, data):
self.elementStack.push(data)
if self.minStack.empty():
self.minStack.push(data)
else:
if data < self.minStack.top():
self.minStack.push(data)
def min(self):
if self.minStack.empty():
return
else:
return self.minStack.top()
def pop(self):
if self.elementStack.empty():
info = "stack is empty, it can not pop"
print info
return
data = self.elementStack.top()
self.elementStack.pop()
if data == self.min() and self.min is not None:
self.minStack.pop()
def process():
data = [5, 3, 4, 2, 1]
minStack = MinStack()
for value in data:
minStack.push(value)
min = minStack.min()
print min
print "####"
while not minStack.empty():
minStack.pop()
print minStack.min()
if __name__ == "__main__":
process()