CDay06
递归
定义:在函数调用过程中又调用自身的现象
斐波拉契数列
Fibnacci数列:0,1,1,2,3,5,8,13,...
Fn = 0, n = 0 ;
Fn = 1, n = 1 ;
Fn = Fn-2 + Fn-1
long long fib(int n)
{
    if(n == 0||n == 1)  return 0;
    return fib(n-2) + fib(n-1);
}
时间复杂度O(2^n),此方法很耗时,不要采用。
 
Q:如何避免重复计算问题?
答:顺序求解子问题,这也就可以避免重复计算(动态规划)
最优解:
long long fib(int n)
{
  if(n == 0||n == 1)  return n;
  long long a = 0, b = 1;
  for(int i = 2;i <= n;i++)
  {
      //计算fib(i)的值
      long long tmp = a + b;
      a = b;
      b = tmp;
  }
  return b;
}
汉诺塔问题

- 边界条件
- 假设会移动 n-1 个盘子,如何移动 n 个盘子(数学归纳法)
递归公式(核心):
- 将 n-1 个盘子移动到 B 上
- 将最大的盘子移动到 C 上
- 将 B 杆上的 n-1 个盘子移动到 C 上
只需关心这一步与递归上一步的关系及边界条件,不要纠结于函数的入栈出栈。
void hanoi(int n, char start, char middle, char target)
{
	int count = 0;
	//边界条件
	if (n == 1)
	{
		printf("%c --> %c\n", start, target);
		return;
	}
	//递归公式
	//把 n-1 个盘子移动到 middle 上
	hanoi(n - 1, start, target, middle);
	//把最大的盘子移动到 target 上
	printf("%c --> %c\n", start, target);
	//把 n-1 个盘子移动到 target 上
	hanoi(n - 1, middle, start, target);
}
有关移动的次数 s(n)

故:
s(n) + 1 = 2s(n-1) + 2 = 2[s(n-1) + 1],为公比为 2 的等比数列
所以,s(n) = 2^n - 1
总结
1、什么情况下可以考虑使用递归?
递归的结构:
- 递:大问题可以分解成若干个子问题,并且子问题的求解与大问题一致。
- 归:可以将子问题的解合并成大问题的解。
2、使用递归时需要注意的问题?
- 重复计算
- 递归的层次不能太深
3、如何写递归?
- 边界条件
- 递归公式

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号