-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmin_val_stack.py
73 lines (62 loc) · 1.75 KB
/
min_val_stack.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
'''
Finds min value of stack in O(1) time using O(n) space
In the worst case, it takes O(n) (w/ a constant factor of 2) space, but on
average it does slightly better because we don't keep a duplicate copy of
every item in the stack.
'''
class Stack:
def __init__(self):
self._stack = []
self._min_stack = []
def push(self, item):
"""Add item to top of stack"""
self._stack.append(item)
# Maintain shadow stack that only contains min items
if (not self._min_stack):
# First element of both stacks
self._min_stack.append(item)
else:
# Only add item to shadow stack if it's less
# than the 'local minimum', viz. a minimum
# element that is below the current stack position
if item <= self._min_stack[-1]:
self._min_stack.append(item)
def pop(self):
"""Remove and return item at the top of stack"""
peeked = self._stack.pop()
# Only remove from shadow stack if we're
# removing a 'local minimum' from the main stack
if (peeked <= self._min_stack[-1]):
self._min_stack.pop()
return peeked
def get_min(self):
"""Return min item or None if stack if empty"""
if self._stack:
return self._min_stack[-1]
else:
return None
def __str__(self):
return '\n'.join(map(str, self._stack[::-1]))
# Create and populate stack
s = Stack()
s.push(3)
s.push(4)
s.push(2)
s.push(2)
s.push(5)
s.push(0)
s.push(1)
s.push(4)
s.push(1)
print s # [1, 4, 1, 0, 5, 2, 2, 4, 3]
assert s.get_min() == 0
s.pop()
s.pop()
s.pop()
assert s.get_min() == 0
s.pop()
assert s.get_min() == 2
s.pop()
s.pop()
assert s.get_min() == 2
print '\n', s