Logic Data Structure
Queue 
FIFO == First In First Out, e.g. waith in a line 
Usages 
BFS  related problems, Tree printout by levelsSliding Window problems(Deque) 
 
 
Only use one Queue, O(n)push, O(1)pop 
Two Queues, O(1)push, O(n)pop1 2 3 4 5 queue = collections.deque() queue.append(1 ) queue.appendleft(2 ) queue.pop() queue.popleft() 
 
 
What is Stack? 
LIFO == Last in First Out, e.g. like a box 
All operation available: push(), pop(), top() 
Iterative DFS 
 
Discussion 
When do we consider “stack” in our algorithm? 
Answer : when we linear scan an array/a string from left to right, and we need to look back the top element!
Find the biggest Rectangle in Histogram 
 
Reverse Polish notation, a  (b + c) -> abc+  
 
String repeatedly deduplication. cabba -> caa -> c 
 
 
 
Design Data Structure Implement a Queue by using two stacks
Key Point : When we pop all the elements from stack1 to stack2, we do not need to pop all the elements to stack1 again! Just put them to stack2 waiting for pop() function! 
Time : pop(),amortized O(1) ; push(),O(1) 
Space : O(n) 
 
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 class  MyQueue (object) :    def  __init__ (self) :         self.stack1 = []          self.stack2 = []      def  push (self, x) :         self.stack1.append(x)     def  pop (self) :         if  len(self.stack2) == 0 :             while  self.stack1:                 self.stack2.append(self.stack1.pop())         return  self.stack2.pop()     def  peek (self) :         if  len(self.stack2) == 0 :             while  self.stack1:                 self.stack2.append(self.stack1.pop())         return  self.stack2[-1 ]     def  empty (self) :         return  len(self.stack1) == 0  and  len(self.stack2) == 0  
Two Stack: original stack & min stack 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class  MinStack (object) :    def  __init__ (self) :         self.stack = []         self.minstack = []     def  push (self, x) :         self.stack.append(x)         cmin = min(x, self.minstack[-1 ]) if  self.minstack else  x         self.minstack.append(cmin)     def  pop (self) :         self.stack.pop()         self.minstack.pop()     def  top (self) :         return  self.stack[-1 ]     def  getMin (self) :         return  self.minstack[-1 ] 
Min Stack Follow Up 
How to optimize the space usage of minstack? (Assume there are a lot of duplicates)1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class  MinStack :    def  __init__ (self) :         self.stack = []         self.minStack = []     def  push (self, x) :         self.stack.append(x)         if  not  self.minStack or  x < self.minStack[-1 ][0 ]:             self.minStack.append((x, len(self.stack)))     def  pop (self) :         self.stack.pop()         if  len(self.stack) < self.minStack[-1 ][1 ]:             self.minStack.pop()     def  top (self) :         return  self.stack[-1 ]     def  getMin (self) :         return  self.minStack[-1 ][0 ] 
 
 
popMax()  – Retrieve the maximum element in the stack, and remove it. If you find more than one maximum elements, only remove the top-most one.TreeMap in Java!!! 
 
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 class  MaxStack (object) :    def  __init__ (self) :         self.stack = []     def  push (self, x) :         self.stack.append((x, max(x, self.stack[-1 ][1 ] if  self.stack else  None )))             def  pop (self) :         return  self.stack.pop()[0 ]     def  top (self) :         return  self.stack[-1 ][0 ]     def  peekMax (self) :         return  self.stack[-1 ][1 ]     def  popMax (self) :         m = self.stack[-1 ][1 ]         temp = []         while  self.stack[-1 ][0 ] != m:             temp.append(self.pop())          self.stack.pop()         map(self.push, reversed(temp))         return  m 
TODO : Using Stack for Selection Sort; Implement Deque using stacks 
 
1 2 3 4 5 6 7 8 9 10 11 12 class  Solution (object) :    def  isValid (self, s) :         stack = []         pdic = {'(' :')' , '{' :'}' , '[' :']' }         for  ch in  s:             if  ch in  "({[" :                 stack.append(pdic[ch])             else :                 if  len(stack) == 0  or  stack[-1 ] != ch:                     return  False                  stack.pop()         return  len(stack) == 0  
O(1) Stack Remove 3 or more duplicates repeatedly 
Stack + traversal pointer 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 def  removeDuplicates (s) :    stack = []     i = 0      print(s)     while  i < len(s):         if  len(stack) > 1  and  s[i] == stack[-1 ] == stack[-2 ]:             while  i < len(s) and  s[i] == stack[-1 ]:                 i += 1              stack.pop()             stack.pop()         else :             stack.append(s[i])             i += 1      return  stack if  __name__ == "__main__" :    string = raw_input()     res = removeDuplicates(string)     print(res) 
Use Two pointers to imitate the stack!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 def  removeDuplicates (s) :    i = 0      slow = -1      while  i < len(s):         if  slow > 0   and  s[i] == s[slow] == s[slow-1 ]:             while  i < len(s) and  s[i] == s[slow]:                 i += 1              slow -= 2          else :             slow += 1              s[i], s[slow] = s[slow], s[i]             i += 1      return  s[:slow+1 ] if  __name__ == "__main__" :    string = raw_input()     res = removeDuplicates(list(string))     print(res) 
 
 
Stack, Space : O(m + n) 
Two Pointers, Space : O(1) 
 
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 class  Solution (object) :    def  backspaceCompare (self, S, T) :         p1, p2 = len(S)-1 , len(T)-1          while  p1 >= 0  or  p2 >= 0 :             back1 = 0              while  (p1 >= 0  and  S[p1] == '#' ) or  back1 > 0 :                 back1 += 1  if  S[p1] == '#'  else  -1                  p1 -= 1              back2 = 0              while  (p2 >= 0  and  T[p2] == '#' ) or  back2 > 0 :                 back2 += 1  if  T[p2] == '#'  else  -1                  p2 -= 1              if  p1 < 0  and  p2 < 0 :                 return  True              elif  p1 < 0  or  p2 < 0 :                 return  False              else :                 if  S[p1] != T[p2]:                     return  False                  else :                     p1 -= 1                      p2 -= 1          return  p1 == p2