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 个盘子(数学归纳法)

递归公式(核心):

  1. 将 n-1 个盘子移动到 B 上
  2. 将最大的盘子移动到 C 上
  3. 将 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、如何写递归?

  • 边界条件
  • 递归公式
posted @ 2023-02-02 16:26  MyXjl  阅读(15)  评论(0编辑  收藏  举报