150. 逆波兰表达式求值
使用栈
-
post-order转in-order
- Post-order: left-right-root
- In-order: left-root-right
-
记得把result push进stack
class Solution:
def evalRPN(self, tokens):
stack = []
for token in tokens:
if token not in "+-/*":
stack.append(int(token))
continue
number_2 = stack.pop()
number_1 = stack.pop()
result = 0
if token == "+":
result = number_1 + number_2
elif token == "-":
result = number_1 - number_2
elif token == "*":
result = number_1 * number_2
else:
result = int(number_1 / number_2)
stack.append(result)
return stack.pop()
239. 滑动窗口最大值
使用单调递减队列
- 使用deque来实现单调递减队列
- 维护一个到index i为止的,最大长度为k的单调递减队列
- 当一个元素被移出窗口时,也将它从队列中移除
- 当一个元素被移入窗口时,将它push进队列,并维护队列的单调性
# Time complexity: O(N)
# Space complexity: O(k)
from collections import deque
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
# decreasing queue
class MyQueue:
def __init__(self):
self.my_queue = deque()
# if max is moving from the window, pop it.
def pop(self, value):
if self.my_queue and value == self.my_queue[0]:
self.my_queue.popleft()
def push(self, x):
while self.my_queue and self.my_queue[-1] < x:
self.my_queue.pop()
self.my_queue.append(x)
def front(self):
return self.my_queue[0]
my_queue = MyQueue()
for i in range(k):
my_queue.push(nums[i])
res = [my_queue.front()]
my_queue.pop(nums[0])
l, r = 1, k
while r < len(nums):
my_queue.push(nums[r])
res.append(my_queue.front())
my_queue.pop(nums[l])
l += 1
r += 1
return res
347. 前 K 个高频元素
使用库函数,数个数然后排序
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
nums_count = Counter(nums)
sort_nums_count = sorted(
nums_count.items(), key=lambda x: x[1], reverse=True)
return [sort_nums_count[i][0] for i in range(k)]
使用heapq.nlargest
-
heapq.nlargest(n, iterable, key=None)从 iterable 所定义的数据集中返回前 n 个最大元素组成的列表。 如果提供了 key 则其应指定一个单参数的函数,用于从 iterable 的每个元素中提取比较键 (例如
key=str.lower)。 等价于:sorted(iterable, key=key, reverse=True)[:n]。
heapq.nlargest在 n 值较小时性能最好。 对于更大的值,使用
sorted()函数会更有效率。 此外,当n==1时,使用内置的min()和max()函数会更有效率。 如果需要重复使用这些函数,请考虑将可迭代对象转为真正的堆。
from collections import Counter
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
# O(1) time
if k == len(nums):
return nums
# 1. build hash map : character and how often it appears
# O(N) time
count = Counter(nums)
# 2-3. build heap of top k frequent elements and
# convert it into an output array
# O(N log k) time
return heapq.nlargest(k, count.keys(), key=count.get)
使用小根堆
- 维护一个大小为k的小根堆,将所有的数以frequency的大小排序
- 如果大小大于k,就pop出堆顶
- 这样我们遍历完整个count map之后,剩下在堆里的元素,就是frequency最大的k个了
heapq.heappush和heapq.heappop维护的都是最小堆
# Time complexity: O(Nlogk)
# Space complexity: O(N+k)
from collections import Counter
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
if k == len(nums):
return nums
count = Counter(nums)
min_heap = []
for key, freq in count.items():
heapq.heappush(min_heap, (freq, key))
# 维护一个长度为k的小根堆
if len(min_heap) > k:
heapq.heappop(min_heap)
return [min_heap[i][1] for i in range(k)]
栈与队列总结
栈经典题目
栈在系统中的应用
- 递归的实现是栈:每一次递归调用都会把函数的局部变量、参数值和返回地址等压入调用栈中,然后递归返回的时候,从栈顶弹出上一次递归的各项参数,所以这就是递归为什么可以返回上一层位置的原因。
括号匹配问题
这里有三种不匹配的情况,
- 第一种情况,字符串里左方向的括号多余了 ,所以不匹配。
- 第二种情况,括号没有多余,但是 括号的类型没有匹配上。
- 第三种情况,字符串里右方向的括号多余了,所以不匹配。
字符串去重问题
把字符串顺序放到一个栈中,然后如果相同的话 栈就弹出,这样最后栈里剩下的元素都是相邻不相同的元素了。
逆波兰表达式问题
每一个子表达式要得出一个结果,然后拿这个结果再进行运算(将每个子表达式的result push进栈)
队列的经典题目
滑动窗口最大值问题
-
主要思想是队列没有必要维护窗口里的所有元素,只需要维护有可能成为窗口里最大值的元素就可以了,同时保证队列里的元素数值是由大到小的。 那么这个维护元素单调递减的队列就叫做单调队列,即单调递减或单调递增的队列。
-
设计单调队列的时候,pop,和push操作要保持如下规则:
- pop(value):如果窗口移除的元素value等于单调队列的出口元素,那么队列弹出元素,否则不用任何操作
- push(value):如果push的元素value大于入口元素的数值,那么就将队列出口的元素弹出,直到push元素的数值小于等于队列入口元素的数值为止
保持如上规则,每次窗口移动的时候,只要问que.front()就可以返回当前窗口的最大值。
-
单调队列不是一成不变的,而是不同场景不同写法,总之要保证队列里单调递减或递增的原则,所以叫做单调队列。不要以为本地中的单调队列实现就是固定的写法。
求前 K 个高频元素
- 使用大小固定为k的小根堆(优先队列)进行排序
- 其实就是一个披着队列外衣的堆,因为优先级队列对外接口只是从队头取元素,从队尾添加元素,再无其他取元素的方式,看起来就是一个队列。而且优先级队列内部元素是自动依照元素的权值排列。
- 堆是一棵完全二叉树,树中每个结点的值都不小于(或不大于)其左右孩子的值。 如果父亲结点是大于等于左右孩子就是大顶堆,小于等于左右孩子就是小顶堆。
- 所以大家经常说的大顶堆(堆头是最大元素),小顶堆(堆头是最小元素),如果懒得自己实现的话,就直接用priority_queue(优先级队列)就可以了,底层实现都是一样的,从小到大排就是小顶堆,从大到小排就是大顶堆。
- 本题就要使用优先级队列来对部分频率进行排序。 注意这里是对部分数据进行排序而不需要对所有数据排序!