登录以参加训练计划
算法思维6个层次
一、概述
算法题的解题思路主要涉及三个方面:编程、数据结构和算法思维。
编程和数据结构相对简单,也是程序员日常工作的一部分,因此程序员一般都能熟练掌握。
算法思维灵活多变,程序员的工作生活也很少触及,市面上也缺乏系统而全面的学习资料,因此很多程序员对其相对陌生,面试也常常挂在了这里。
因此本课程解题思路的重点是算法思维,需要学员具备一定的编程和数据结构的基础。
二、算法思维层次
面试算法题的解题思路可以简单总结为以下几个层次:
L0:编程模拟
部分算法题不仅描述了想要的结果,还清楚地描述了求得结果的具体步骤。
对于这类题目,根据题目的要求编写代码即可,不涉及复杂的算法思维。(这部分简单理解即可,实际高级别考试都是考思维题为主)
题目示例:
L1:暴力穷举
绝大多数算法题都只描述了想要的结果,并没有描述求得结果的具体步骤,因此需要程序员自己来设计具体步骤。
一个听起来容易实施起来却并不容易、听起来很笨实际上却很有效的算法思维,就是:暴力穷举。
有些暴力穷举显而易见,我们可以枚举出所有可能性,再从中找出最优结果:
- 作用于数组,就是遍历数组所有元素
1295. 统计位数为偶数的数字
522. 最长特殊序列 II - 作用于树与图,就是通过深度优先和广度优先遍历所有节点
965. 单值二叉树
1129. 颜色交替的最短路径 - 作用于集合,就是二进制枚举
78. 子集
77. 组合 - 作用于排列、组合、有序路径等,就是回溯
17. 电话号码的字母组合
980. 不同路径 III
有些暴力穷举比较隐晦,需要做合理的“子问题拆分”,再穷举所有子问题,再根据子问题的解得到父问题的解。
关于如何做子问题拆分,可以参考动态规划模板体系中的《最优子结构全景图》。
穷举过程中有时可加入一些策略,虽然整体的搜索空间没有减少,但优先搜索了概率更大的分支,也是一种优化手段,参考“启发式搜索”。
暴力穷举法虽然看起来性能不高,但却是其他算法有效的基础,在互联网大厂的面试中举足轻重。
L2:快速跳过不必要的分支(剪枝)
穷举所有可能性虽然能够得到正确的结果,但时间复杂度较高。
如果数据存在某些特征或题目给出某些条件,则可根据规则跳过某些不必要的分支,从而降低时间复杂度。
- 如果关注的数组元素位置比较接近,可通过
滑动窗口降低时空复杂度
209. 长度最小的子数组
978. 最长湍流子数组 - 如果数组是有序的,可通过二分查找将复杂度从O(n)降低为O(logn)
704. 二分查找
378. 有序矩阵中第 K 小的元素 - 如果二叉树是搜索树,可通过二分查找将复杂度从O(n)降低为O(logn)
700. 二叉搜索树中的搜索
230. 二叉搜索树中第K小的元素 - 如果通过某种子问题的最优解可直接推导出父问题的最优解,可使用贪心策略
55. 跳跃游戏
228. 汇总区间 - 如果题目给出了其他限定条件,可通过这些条件跳过不必要的分支
37. 解数独
51. N 皇后
L3:预处理
对数据的有效预处理,也可以降低算法的时空复杂度。
- 通过预处理使数据能快速跳过不必要的分支
比如将数组排序后可使用二分查找等
378. 有序矩阵中第 K 小的元素
976. 三角形的最大周长 - 将一些公共逻辑提前计算并存储,可降低后续处理的复杂度
比如提前计算数组的前缀和等
303. 区域和检索 - 数组不可变
1314. 矩阵区域和
L4:子问题去重
一些算法是通过将大问题拆分为多个小问题来解决的,这些小问题又进一步拆分为更小的小问题来解决。
在小问题的不断拆分过程中,会出现很多重复子问题,对这些重复子问题的有效去重,可有效降低时间复杂度,相当于用空间换时间。
- 记忆化搜索
在计算大问题时,先递归地将依赖的小问题计算完,然后再根据小问题的最优解推导出大问题的最优解。
计算过程中用记忆化表保存小问题的计算结果,下次再递归到这个小问题时,直接从记忆化表取结果,避免重复计算。
980. 不同路径 III
329. 矩阵中的最长递增路径 - 动态规划DP
从小到大计算<=目标问题的所有问题,并用dp数组存储这些问题的解,直到得到目标问题的解。
1027. 最长等差数列
198. 打家劫舍
关于记忆化搜索和动态规划的更多介绍,参考《理解动态规划》。
L5:数学
一些算法题是可以通过数学方法降低时空复杂度,甚至直接给出答案的。
- 通过数学方法降低时空复杂度的例子
89. 格雷编码
172. 阶乘后的零 - 通过数学方法直接给出答案的例子
877. 石子游戏
509. 斐波那契数
三、总结
随着算法层次的不断提升,算法时间复杂度在不断下降。
L0表示仅考察编程不涉及算法,L1表示搜索整个空间,L2/L3/L4通过算法思维降低搜索空间,L5通过数学方法降低搜索为空间。
对于准备参加互联网大厂算法面试的程序员而言,更应该关注哪个层次的算法呢?是最高效的L5数学吗?
我认为恰恰相反,程序员更应该关注L0和L1,因为这决定了能否在面试中将题做出来,在能做出来的前提下,再借助L2/L3/L4的思想不断优化算法的时空复杂度。
至于L5数学方法,这是数学家应该研究的东西,程序员不可能也没必要记住太多数学公式,刷题过程中根据碰到的具体例题适量补充一些即可。
章节 2. L1 暴力穷举
无效
该章节目前不可挑战,请先完成以下章节:
- 章节 1. L0 模拟 (已完成 0%)
| 题目 | 尝试 | AC | 难度 |
|---|---|---|---|
| 2 A+B 输入输出练习II | 0 | 0 | (无) |
| 3 A+B 输入输出练习III | 1 | 1 | 10 |
章节 3. L2 剪枝
无效
该章节目前不可挑战,请先完成以下章节:
- 章节 1. L0 模拟 (已完成 0%)
| 题目 | 尝试 | AC | 难度 |
|---|---|---|---|
| 2 A+B 输入输出练习II | 0 | 0 | (无) |
| 3 A+B 输入输出练习III | 1 | 1 | 10 |
章节 4. L3 预处理
无效
该章节目前不可挑战,请先完成以下章节:
- 章节 1. L0 模拟 (已完成 0%)
| 题目 | 尝试 | AC | 难度 |
|---|---|---|---|
| 2 A+B 输入输出练习II | 0 | 0 | (无) |
| 3 A+B 输入输出练习III | 1 | 1 | 10 |
章节 5. L4 子问题去重
无效
该章节目前不可挑战,请先完成以下章节:
- 章节 1. L0 模拟 (已完成 0%)
| 题目 | 尝试 | AC | 难度 |
|---|---|---|---|
| 2 A+B 输入输出练习II | 0 | 0 | (无) |
| 3 A+B 输入输出练习III | 1 | 1 | 10 |
章节 6. L5 数学
无效
该章节目前不可挑战,请先完成以下章节:
- 章节 1. L0 模拟 (已完成 0%)
| 题目 | 尝试 | AC | 难度 |
|---|---|---|---|
| 2 A+B 输入输出练习II | 0 | 0 | (无) |
| 3 A+B 输入输出练习III | 1 | 1 | 10 |
- 参加人数
- 1
- 创建人