算法思路总结

过去一年基本上都在练习算法了,人菜瘾大刷了不少题,做个总结吧。


Python


二叉树

刷题建议从二叉树开始,俗话说的好「递归在手,遇 Tree 不愁」,主要是二叉树的思路有固定的模板,而且也不太可能考到红黑树那个级别,难一点也只会和 Graph 相关,一开始比较容易建立信心。

应该算是心理压力最大的一类了,但是只要没有超纲,套路并不多

并查集

英文名 Union Find,其实也刚好对应需要实现的两个方法 union(p, q) -> Nonefind(p) -> int ,也刚好对应两个主要的思想「按秩合并」「路径压缩」。

一般遇到连通相关的题目,个人是优先用并查集的,因为比较模板化,相比于 DFS 和 BFS,思路比较简单,也没什么出错的空间。

需要注意连通的广义的定义,两个邮箱对应同一个人,岛屿中 land 相互连接。

但是尤其需要注意的是,这里连通的双向性,比如炸弹 A 爆炸时可以引爆 B,并不意味着炸弹 B 可以爆炸引爆 A,这里连接是单向的。

字典树

如果题目没有提到字典树,不太容易想到这个思路。更多时候是一种优化方案,比如矩阵中查找字符串,如果不提前建立一个 Trie,那么在搜索的时候肯定会 TLE 了。

数组

数组算是最难的一类了,因为花样比较多

矩阵

链表

滑动窗口

一般按照题意就可以想到这个思路了

需要在窗口内维护顺序时,可以使用 SortedList,O(logN) 的复杂度,LeetCode 官方支持这个第三方的 sortedcontainer 库

二分

一般是 10^4 或者题目要求 O(logN) 的复杂度了

正相关的题目可以试试二分,比如吃香蕉的最慢速度、计算平方根

单调栈、单调队列

往往觉得这种解法很神奇

顺着题意去模拟这个过程,在求每个阶段的值的时候,可能会注意到这个方向。

84. Largest Rectangle in Histogram

239. Sliding Window Maximum

前缀和

前缀和的思想很简单,但是变种非常多

DP

常说状态转换方程,但是一般可能没那么容易找出来。实用一点的方法是,先寻找可能的操作,每一个操作后可能对应不同的状态。比如股票的买卖、冷冻期。

有些 DP 原型会藏的比较深

字符串

和数组一样也是难点,因为变化可能比较多

Math

最绝望的一类题了吧,高考都是多少年前的事情了

BIT

BFS

回溯

几乎通用的模板:

1for o in options:
2    state[i] = o
3    if dfs(i + 1):
4        return True
5    else:
6        state[i] = None

37. Sudoku Solver

980. Unique Paths III

51. N-Queens

最短路径

大部分是 BFS,其余大多是 DP 或者 Dijkstra

建议首先考虑 Dijkstra,因为对于常见的有向加权图,只有这一种解法,没有什么变化。

对于 BFS,当路径可以重复访问时,也许需要添加状态记录访问情况

带限制的有向图最短路径,可以用 DP,如 787. Cheapest Flights Within K Stops,这个题号也是藏了个梗。

扫描线

天上最多的飞机、同时最多上自习的人、merge 区间

需要注意的是,最后结果的定义是否要包含起点与结束点,比如求人口最多的一年,那么是否需要包含这一年的死亡人数。

变体:218. The Skyline Problem391. Perfect Rectangle

其他神奇的思路