classSolution:def__init__(self):""" Initialize your data structure here. """ self.queue=[]defpush(self,x):""" Push element x onto stack. """ self.queue.append(x)defpop(self):""" Removes the element on top of the stack and returns that element. """return self.queue.pop()if self.queue elseNonedeftop(self):""" Get the top element. """return self.queue[-1]if self.queue elseNonedefisEmpty(self):""" Returns whether the stack is empty. """returnnot self.queue
常见题型:
Deduplication and Repeatedly deduplication, Leetcode 71, simplify path
作为辅助实现更高级的data structure: two stack -> queue, min stack; max stack
表达式计算、decode
单调栈 eg. Histogram中找到最大的长方形
括号匹配
defisValid(seq): s=[]for c in seq:if c in'([{': s.append(c)elif c==')'and (s and s[-1]=='('): s.pop() ...
或者我们用dict吧...
defisValid(seq): left_bracket = [] matching_bracket ={'{':'}','[':']','(':')'}for b in brackets:if b in matching_bracket: left_bracket.append(b)elifnot left_bracket or matching_bracket[left_bracket[-1]]!=b:returnFalseelse: left_bracket.pop()returnnot reft_bracket
import operatordefarithmetic_expression_evaluation(terms): operands=[] operators=[] ops ={'+': operator.add,'-': operator.sub,'*': operator.mul,'/': operator.truediv}for term in terms:if term =='(':continueelif term ==')': right, left = operands.pop(), operator.pop() operands.append(ops[operators.pop])(left, right))elif term in ops: operators.append(term)else: operands.append(int(term))return operands[0]
deftokenize(s): from_num, num =False,0for c in s:if c.isdigit(): from_num =True num =10*num+int(c)else:if from_num:yield num from_num, num =False,0ifnot c.isspace():yield cif from_num:yield numimport operatordefarithmetic_expression_evaluation(terms): operands=[0] operators=['+'] ops ={'+': operator.add,'-': operator.sub,'*': operator.mul,'/': operator.truediv}for term in terms:if term =='(': operators.append('+') ooperands.append(0)elif term ==')': right, left = operands.pop(), operator.pop() operands.append(ops[operators.pop])(left, right))elif term in ops: operators.append(term)else: operands.append(ops[operators.pop()](operands.pop(), term)return operands[-1]
classSolution():defvalidateStackSequences(self,pushed,popped): s, next_consumed = [],0for item in popped:while (not s or s[-1]!=item) and next_consumed<len(pushed): s.append(pushed[next_consumed]) next_consumed +=1if s[-1]!=item:break s.pop()returnnot s
stack1: to store new elements coming in (enqueue)
- stack1.push()
stack2: to help with dequeue
- case 1: if stack2 is NOT empty: stack2.pop()
- case 2: if stack2 is empty:
- move all elements from stack1 to stack2 one by one
- stack2.pop()
classSolution(object):def__init__(self):""" Initialize your data structure here. """ self.s1 = [] self.s2 = []defpoll(self):""" return : int """ self.move()return self.s2.pop()if self.s2 elseNonedefoffer(self,element):""" input : int element """ self.s1.append(element)defpeek(self):""" return : int """ self.move()return self.s2[-1]if self.s2 elseNonedefsize(self):""" return : int """returnlen(self.s1)+len(self.s2)defisEmpty(self):""" return : boolean """returnnot self.s1 andnot self.s2defmove(self):ifnot self.s2:while self.s1: self.s2.append(self.s1.pop())
Enqueue: Time O(1)
Dequeue: Time worst case O(n), amortized O(1)
amortized time vs average time:
amortized: amortize all operations within input (不管是什么样的input)
average: average over all possible inputs (和输入输出有关系 不能保证某一种情况)
Implement a stack using 2 queues
only 2 APIs available: enqueue, dequeue
enqueue():
dequeue():
- if the queue is not empty, return the first element
- if the queue is empty, return null
stack [ 1 2 3 4
Q1 <-- <--
Q2 <-- <--
如果Q1没空,就把Q1塞到Q2,如果空了,返回最后的那个
classSolution {privateQueue<Integer> q1;privateQueue<Integer> q2; /** Initialize your data structure here. */publicSolution() { q1 =newArrayDeque<>(); q2 =newArrayDeque<>(); } /** Push element x onto stack. */publicvoidpush(int x) {q1.offer(x); } /** Removes the element on top of the stack and returns that element. */publicIntegerpop() {Integer prev=q1.poll();Integer curr=q1.poll();while (curr!=null) {q2.offer(prev); prev=curr; curr=q1.poll(); }Queue<Integer> tmp = q1; q1 = q2; q2 = tmp;return prev; } /** Get the top element. */publicIntegertop() {Integer ret =pop();if (ret!=null){q1.offer(ret); }return ret; } /** Returns whether the stack is empty. */publicbooleanisEmpty() {returntop()==null; }}
Implement a stack using 1 queue
如果此时多了一个size()的API
stack [ 1 2 3 4
Q <-- <--
做size-1次:拿出来再从尾部塞回去
Implement a stack with Max API
Solution 1: Brute Force, O(n), iterate each element in the stack to find the max
Solution 2: Trade space for time
Current top of stack (x, x_max)
New value y:
push: if y>x_max, store (y, y) else, store (y, x_max)
classSolution(object):def__init__(self):""" initialize your data structure here. """ self.stack = []defpush(self,x):""" input : int x return : """ tmp = xif self.stack: tmp =min(tmp, self.min()) self.stack.append((x, tmp))defpop(self):""" return : int """ifnot self.stack:return-1else: tmp = self.stack.pop()return tmp[0]deftop(self):""" return : int """return-1ifnot self.stack else self.stack[-1][0]defmin(self):""" return : int """return-1ifnot self.stack else self.stack[-1][1]
优化 如果有很多duplicate
CART 如果有size就可以用tuple
加counter <1, 100> 代表有100个1
第一次出现它时里面有几个元素 <1,2> 出现1的时候是第二个位置
也可以用3个stack,不是存tuple而是又加一个stack来存位置
Follow up: duplicate element
优化,可以只有数值有变时再存min
Push x: stack.append(x)
Case 1: x<=getMin(): minStack.append(x)
Case2: x>getMin(): Do nothing
Pop x:
if stack[-1]==getMin()
minStack.pop()
stack.pop()
Implement a deque with multiple stacks
left XXXXXXXXXXXXXXXXXXXXXXXXX right
l.add() r.add()
l.remove() r.remove()
2 stacks
]s1 s2[
s1: simulate the left end of the deque
s2: simulate the right end of the deque
left.add(): s1.push() O(1)
right.add(): s2.push() O(1)
left.remove():
- if s1 is not empty, just stack1.pop() O(1)
- if s2 is empty,
- move all elements from s2 to s1 O(n) worst
- stack1.pop()
right.remove(): similar
L. remove () R.remove() L. remove() R.remove() L. remove() R.remove() L. remove() R.remove() −2n+1−2(n−1)+1−2(n−2)+1−2(n−3)+1−−−−⋯
Amortized time =n2∗(n+(n−1)+(n−2)+…+1)+n=nn∗(n−1)+n=(n−1)+1=n
classSolution:def__init__(self):""" Initialize your data structure here. """ self.left = [] self.right = [] self.buffer = []defisEmpty(self):""" Return true if the deque is empty otherwise return false """returnFalseiflen(self.left)+len(self.right)+len(self.buffer)!=0elseTruedefsize(self):""" return Size of deque """returnlen(self.left)+len(self.right)defofferFirst(self,x):""" Offer x to the first position of the deque """ self.left.append(x)defofferLast(self,x):""" Offer x to the last position of the deque """ self.right.append(x)defpeekFirst(self):""" Peek the first element of the deque. Return None if the deque is empty. """ifnot self.left: self.move(self.right, self.left)return self.left[-1]if self.left elseNonedefpeekLast(self):""" Peek the last element of the deque. Return None if the deque is empty. """ifnot self.right: self.move(self.left, self.right)return self.right[-1]if self.right elseNonedefpollFirst(self):""" Poll the first element of the deque. Return None if the deque is empty. """ifnot self.left: self.move(self.right, self.left)return self.left.pop()if self.left elseNonedefpollLast(self):""" Poll the last element of the deque. Return None if the deque is empty. """ifnot self.right: self.move(self.left, self.right)return self.right.pop()if self.right elseNonedefmove(self,fromS,toS):""" helper function to serve as a buffer; move half of the element from fromS to toS """ifnot fromS:return halfsize =len(fromS)//2while halfsize>0:#这个太坑爹了 没有等号!!不然一个元素的时候要玩完 self.buffer.append(fromS.pop()) halfsize-=1while fromS: toS.append(fromS.pop())while self.buffer: fromS.append(self.buffer.pop())
one sentence: use selection sort to sort
data structure: record globalmin when buffering elements from s1 to s2; when s1 is empty, put the global_min in s3, put all but s2 back to s1.
algorithm (high level--detail):
defisValid(S):ifnot S:returnFalse key ='abc' stack = []for x in S:if x!='c': stack.append(x)else:iflen(stack)<2:returnFalseif key ==''.join([stack[-2], stack[-1], x]): stack.pop() stack.pop()else:returnFalsereturnlen(stack)==0
Time: O(n)
Space: O(n)
Leetcode 856 表达式求值
()has score 1
AB has score A+B
(A) has score 2*A
defscoreofparenthesis (S): stack = [0]for x in S:if x =='(': stack.append(0)else: top = stack.pop()if top ==0: stack[-1]+=1else: stack[-1]= top*2+ stack[-1]return stack[0]
defevaluate(seq): s=[]for c in seq:if c=='(': s.append(c)else: acc=0while s and s[-1]!='(': acc += s.pop() s.pop()#pop the ( s.append(max(acc*2, 1))#when acc=0returnsum(s)#because ()() s=[1,1]