Stack
Last in First Out list就是一个天然的stack,不需要单独定义class。
push
pop
top
从左到右linear scan,需要不断回头看过去的元素时,使用stack
常见题型:
Deduplication and Repeatedly deduplication, Leetcode 71, simplify path
作为辅助实现更高级的data structure: two stack -> queue, min stack; max stack
表达式计算、decode
单调栈 eg. Histogram中找到最大的长方形
括号匹配
或者我们用dict吧...
{: brace-bracket/curly-bracket
[: square bracket
(: parenthesis
简易计算器(+-)
本质是遇到‘)‘后把之前存的数字和operator拿出来做个计算,push回stack,直到stack空为止
逆波兰表达式
Decode
遇到【时把之前的内容暂存起来,保护现场,遇到】时把stack的内容释放出来,恢复现场。
四个变量,cnt, string,cnt_stack, str_stack
遇到 [ : push cnt, string to stack, 重置cnt, string
遇到 ] : pop from stack
946 Validate Stack Sequences (with distinct values)
input: pushed=[1,2,3,4,5], popped = [4,5,3,2,1] output: True
Implement a queue using 2 stacks
两个array,s1用来进元素,s2用来出元素,如果在s2是空的时候还要继续出元素,就把s1的倒进s2里再pop 可以把它想象成底端对底端,中间有一个隐形的墙 --> 6 5 ][4 3 2 1 -->
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()
Enqueue: Time O(1)
Dequeue: Time worst case O(n), amortized O(1)
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,如果空了,返回最后的那个
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)
pop: tmp=lst.pop(), return tmp[0]
Time: O(1)
Space: O(n)
同理,也可以实现getmin
Min Stack
两个stack
stack1 (input) 3 1 4 0 stack2 (min) 3 1 1 0
Push x: stack.append(x)
Case 1: x<getMin(): minStack.append(x)
Case2: x>=getMin(): minStack.append(getMin())
Pop x: stack.pop(), minStack.pop()
Time O(1) Space O(n)
优化 如果有很多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
How to speed up the remove() operation?
3 stacks
4 3 2 1 ]s1 s2[ s3 buffer [ 8 7 6 5 两个stack的时候腹背受敌,只要一边空了,这个操作就非常expensive。如果能只挪一半的元素,不管left.remove还是right.remove就都不怕了。借助s3这个buffer,让左右两边均等。
8 7 6 5 ]s1 s2[ 4 3 2 1 s3 buffer [
Sort Numbers with 2/3 Stacks
3 stacks:
s1 input [ 1 3 2 4 s2 buffer [ global_min s3 output [
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):
2 stacks:
s1 input [ 1 3 2 4 s2 left, output| right, buffer [ global_min
output: put global_min back buffer:
过去得到的 global_min一定小于当前轮的 global_min
方法一:while stack2.size()>stack2.initial_size_before_this_iteration 方法二:while stack2.top()>=global_min keep popping back to s1
Follow Up: duplicate element: add a counter
s1 input [ 1 3 2 4 s2 left, output| right, buffer [ global_min counter
3 stacks 实现merge sort
Leetcode 1003 合法字符串
和括号匹配的问题一样,遇到c时匹配并清空
Time: O(n)
Space: O(n)
Leetcode 856 表达式求值
()has score 1
AB has score A+B
(A) has score 2*A
Last updated