Week03 学习笔记
1 递归的实现、特性以及思维要点
递归的本质就是循环。
要点,联想盗梦空间:
- 向下进入到不同的递归层,向上回到原来的层
- 通过参数传递不同层之间的变量
- 每一层都是拷贝,环境不受其他层影响,但参数会发生改变
递归代码模版:
public void recur(int level, int param) {
// 递归终止条件
if (level > MAX_LEVEL) {
// process result
return;
}
// 处理当层逻辑
process(level, param);
// 到下一层
recur(level + 1, newParam);
// 清理变量
}
思维要点:
- 不要人肉递归
- 找到最近最简单方法,将其拆解成可重复解决的问题(找重复子问题)
- 数学归纳法思维
2 分治、回溯的实现和特性
2.1 分治
本质上是递归,找到重复性。
分治思想,把一个问题划分为多个子问题,最后组合子问题的结果。如阶乘、斐波那契、爬楼梯等
分治代码模版:
public void divideConquer(problem, param1, param2, ...) {
// 终止条件
if problem == null:
printResult();
return;
// 处理当前层逻辑
data = prepareData(problem);
subproblems = splitProblem(problem, data);
// 解决子问题 下探到下层
subresult1 = divideConquer(subproblems[0], p1, ...);
subresult2 = divideConquer(subproblems[1], p1, ...);
subresult3 = divideConquer(subproblems[2], p1, ...);
// 组合子问题
result = processResult(subresult1, subresult2, subresult3, …);
// 清理变量
}
注意,只考虑当前层逻辑。
2.2 回溯
回溯法采用试错的思想,尝试分步解决一个问题。在分步的过程中,如果现有分布不能得到有效解答,则进行回退,再次尝试其他的分步寻找有效解答。如八皇后问题、数独等
回溯法通常用最简单的递归实现,最后有两种情况:
- 找到可能存在的有效答案
- 尝试了所有分步后,没有找到有效答案
最坏情况下,回溯法时间复杂度为指数级别。