july算法5——递归

1.递归定义

  • 直接或间接调用自身
  • 算法思想:
    1)原问题可分解子问题(必要条件)
    2)原与分解后的子问题相似(递归方程)
    3)分解次数有限(子问题有穷)
    4)最终问题可直接解决(递归边界)

2.递归奥义

  • 递归 =递 +归
  • 会想还要会写=>实践出真知
  • 递归奥义——复制自己
    如何造纳米机器人
int robot(int x, int y)//机器人的输入
  if(边界条件)//什么时候不用造了(自己就能干完) 
    return 0; 
  int a = robot(x1, y1);//造一个小的自己帮忙干活 
  int b = robot(x2, y2);//再造一个小的自己帮忙干活 
  return a + b;//自己要做的就是把别人的成果组装起来

3.经典问题

3.1 斐波那切数列

  • 递归方程
    F(n) = F(n – 1) + F(n – 2) //可分解,有穷性

  • 递归边界
    F(0) = 1, F(1) = 1

  • 经典例子
    兔子生兔子
    爬楼梯

  • 直接递归
    时间复杂度预估

  • 优化递归
    不做重复的事

  • 递归转递推
    递归式,递推式?仅仅是方向不一样

  • 为什么用递归
    方便而已!

  • 如何更优?

  • 直接使用公式


3.1.1 公式的问题

N次方如何算?

  • 求an

  • F(n)=aF(n–1), F(0)=1

  • 时间复杂度 O(n)

  • 换种写法
    F(n) = F(n/2)2*a   if n%2==1
      = F(n/2)2    if n%2==0

  • 时间复杂度 O(logn)

  • 斐波那切数列的本质

  • 二阶齐次线性递推式


  • 反复应用


  • 矩阵运算具有结合律性质

  • 适用幂运算的优化方法

  • 时间复杂度: O(logn)

  • 优化: O(指数级) -> O(n) -> O(logn)

  • 本质:减少重复计算

3.1.2 作业

  • 非齐次
    F(n) = F(n – 1) + F(n – 2) + a
  • K阶
    F(n) = F(n – 1) + F(n – 2) + … + F(n – k)
  • 终极作业
    F(n) = F(n – 1) + F(n – 2) + … + F(n – k) + a

3.2 汉诺塔问题

有三根柱子A,B,C。在A上,按照从小到大摞着N片圆盘。现要把圆盘按原顺序重新摆放在C上,并且规定,任何时刻,在小圆盘上不能放大圆盘,一次只能从一个柱子最顶部移一个圆盘到另一柱子顶部

  • 最短移动次数,以及移动方案

  • 试试N=1,N=2

  • N=3?

  • 找到F(N)和F(N-1)的关系
    =>已知F(N-1),如何求出F(N)?

  • 数学归纳法的程序版

  • 方案输出
    从A柱子,利用B柱,到达C柱
    递归时候如何记录状态?
    F(N, A, B, C)

3.3 快速排序

  • 期望时间复杂度O(NlogN)

  • 思想:
    1.找任意一个元素作为中间值m
    2.比m小的放在数组前部,大的放后部
    3.前部后部分别排序(递归)

  • 思想 ->实现

  • 复杂度计算

3.4 二叉树遍历

  • 三种不同的遍历顺序
    前序遍历:ABCDEGF(根左右)
    中序遍历:CBEGDFA(左根右)
    后序遍历:CGEFDBA(左右根)


  • 为什么要区别各种序
    三种序 ->三视图

  • 前序遍历:
    write(根); find(left); find(right)

  • 中序遍历:
    find(left); write(根); find(right)

  • 后序遍历:
    find(left); find(right); write(根);

4.作业

  • 汉诺塔问题,输出步骤并验证
  • 亲手写一个快速排序,并通过测试
  • 实现二叉树遍历的三种方式

参考

  • 1)面试求职 第四期

你可能感兴趣的:(july算法5——递归)