算法训练-Week03

198 阅读2分钟

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 回溯

回溯法采用试错的思想,尝试分步解决一个问题。在分步的过程中,如果现有分布不能得到有效解答,则进行回退,再次尝试其他的分步寻找有效解答。如八皇后问题、数独等

回溯法通常用最简单的递归实现,最后有两种情况:

  • 找到可能存在的有效答案
  • 尝试了所有分步后,没有找到有效答案

最坏情况下,回溯法时间复杂度为指数级别。