按照重要程度排序
- 链表
- 二叉树
- 回溯(动态规划)
- 二分查找
- 动态规划
- DFS/BFS,题目还经常考
- 双指针
- 滑动窗口
- 单链表中进行两个节点互换时,看似简单其实有坑
- 当两元素相邻和不相邻时,处理逻辑是不同的
栈的题目不是很多,经典的可能有几种:
- 消消乐
- 在leetcode上对应的题目有:计算器、括号匹配、字符串重复字符删除
- 剑指 Offer 31. 栈的压入、弹出序列
- 该题写的比较艰难
- 很早写过一次,但并没有用栈的思路,而是用数学规律来解决的。其实规律也不好找,相比之下用栈的思路解决更容易想到
- 用栈的思路时,思路不够清晰明了,导致出了两次错误
- 思路清晰很重要
递归算法时间复杂度比较差,可以使用:
- 递归树
- 递推公式
来分析具体的时间复杂度
主要考虑函数调用栈压栈深度有关
- 问题可不可以划分为相同步骤的子问题
- 子问题的处理逻辑和完整问题相同
- 有没有递归结束条件
- 记得加入备忘录,避免重复计算
- 递归容易触发内存的栈溢出和耗时太大
- 栈溢出的问题可以通过考虑使用备忘录避免重复计算(如果有重复计算的)
- 耗时太大的话,可以考虑能否使用动态规划一次性搞定
- 剑指 Offer 25. 合并两个排序的链表,使用递归思路做时,子问题的划分不太容易
- 区间问题
- 提示:先排序
- 排序链表的解法-迭代法如何实现?使用快排实现的为何超时?应该看下题解中的快排实现
- 合并有序数组的题目,有更优的解法,应该再实现一遍
- 自己分析一遍每个排序算法的时间、空间复杂度
- 看似简单的排序算法,如插入排序,想要一点错没有的写出来还是不容易的。主要难点在于,核心思想了解。但具体到实现代码上,很容易出现错误
- 如何解决?思路一定要想清楚,对照思路翻译代码
- 避免复杂的代码逻辑,要将复杂代码简单化
- 向冒泡、选择、插入、归并等排序算法,还是要练一下,看有没有什么坑
- 对链表使用这些排序算法,在代码实现上还是有难度的
填一个坑
- 寻找比目标字母大的最小字母,耗时大
- 在排序数组中查找元素的第一个和最后一个位置,这个原以为想出办法了,但还是因为边界问题没有一把唆。另外,实现上不是太优雅,但也还算过得去。看还有没有更优雅的实现
- 搜索旋转排序数组,该题的边界判断条件容易忽略掉
- 填一个坑,了解常见的哈希冲突的解法,并看一下OC和Swift中字典结构的哈希解决办法;再深入了解一下跟哈希相关的equal知识点
- 三数之和问题,习题讲解中的往哈希表中添加数据的代码有问题
- 把二叉搜索树转换为累加树,有没有更优雅的实现。当然有,可以参考相同题1038. 从二叉搜索树到更大和树的实现
- 剑指 Offer II 053. 二叉搜索树中的中序后继,一个很考察对递归理解深度的题。在哪里进行递归退出是该问题的关键点
- 114. 二叉树展开为链表,看有没有更优雅的实现
从一个场景应用来认识字符串匹配
敏感词匹配
敏感词库假设很大,在每一篇公众号文章发表后,都要对其进行敏感词检测,如果敏感词过多,就提醒用户进行自我审核
该部分重点是Trie树
回溯题目中去重问题是难点
- 回溯的算法时间复杂度分析
-
[子集]和[子集 II]问题的关键点在于像背包问题一样,放与不放
-
组合,该问题转化为k阶段或n阶段都可以
-
子集 II和全排列 II的实现中,使用哈希表将重复数据进行归并的方式比较好用
- 当然,也可以考虑另外使用一个used数组进行剪枝操作
- 不管是used还是通过哈希表,其实都不好想
-
组合总和 III,该部分每个阶段可选列表的判断逻辑有没有优雅的实现,在去重方面有没有优雅的实现
-
分割回文串该题一开始没太看懂,但还比较常考,操蛋。不好做,算法写的不容易懂
- 和复原 IP 地址属于类似提醒。这个题核心逻辑方面写的很难受,具体是字符串操作部分,需要看看好的实现,还需要练练
对拓扑排序的理解,大致是有一堆任务,任务之间有依赖关系,比如要完成任务B,必须先完成A。
拓扑排序的任务就是通过算法判定这堆任务能否正常的完成。
-
遍历一遍任务,将每个任务的前置任务记录下来,构造出如表所示的样子:
任务/依赖任务数目 A B x 1 0 -
然后从表中选择依赖任务数为0的任务开始执行(其实就是输出到结果列表),每执行一个任务,就及时更新一下上面的表
-
重新执行2,直到找不到依赖任务数目为0的任务
-
如果最后发现还剩下任务没有执行,则说明该任务拓扑排序无法正常完成,反之可以正常完成
- 需要练一息DFS和BFS的代码
- 面试题 16.19. 水域大小,时间不太理想
- 岛屿数量一题也需要看下优雅实现
没怎么看提醒套路的视频就开始做题了。发现,有几个题目如果将它转化为图的数据结构,就能很容易的应用图的算法。但一开始却一直想不到,而是使用了通用的回溯思想去做,致使算法编写难度明显变大,其实视频中是有讲到的
我自己的感觉是,如果一个题目想的特别费劲,应该尝试换一下思路
- kahn算法时间复杂度
- 拓扑排序的DFS实现
- 检测环的存在算法
动态规划适用的问题:能用回溯来解决,并且存在重复子问题。就可以用动态规划来优化
动态规划中,比较难的是状态以及状态方程的定义。该部分通过列举几个经典状态模型,使得更容易上手
0-1背包、完全背包、多重背包、二维费用背包
- 快慢指针、前后指针、两数组两个指针
- 快排的partition函数
适合解决连续序列问题
需要了解常见的应用场景:比如有一个数组,需要频繁的考察某个连续的区间