算法导论三-分治法

分治法

  • 简单说,分治法即分而治之,即将问题分化为小问题来处理。
  • 简化起来看有二到三个步骤:
    • 分:将问题分解为若干子问题(复杂度n降低)。
    • 治:递归解决子问题。
    • 合:合并子问题的解。
  • 常见分治法的递归式为: T(n) = 2T(n/2) + θ(n) ,即分为两个解法一样的子问题,以及额外的线性时间。满足主方法的条件2,可得解为: T(n) = n * lg n。

归并排序

目标:数组排序

分治法:
  • 分:将数组分成两个数组
  • 治:递归排序
  • 合:合并结果,已有序的子序列合并
时间复杂度: T(n) = 2 T(n/2) + θ(n) 根据主方法(2)得出解为: T(n) = n log n

二分查找

目标:在一个已排序的数组中查找某个值
原始方式:通过一次遍历查找,时间复杂度: T(n) = n 。
二分查找:通过查看数组中间的值进行查找,时间复杂度: T(n) = log n 。(log n 远小于n)

分治原理:
  • 分:取中间值进行比较,从而将数组分成了两段
  • 治:递归从其中一个数组取中间值进行比较
  • 合:如果找到即结束,否则确定从哪边进行递归,常量时间。
时间复杂度: T(n) = T(n/2) + θ(1) 根据主方法(2)得出解为: T(n) = log n

乘方

目标:给出一个数 X, 整数 n, 求 n 个 X 相乘的值。
原方式:n个 X 相乘,需要计算n次结果,时间复杂度: T(n) = θ(n)

分治法:
  • 先考虑乘方原理,例如 5^4 = 5 * 5 * 5*5 = 5^(2+2) = 5^2 * 5^2 ,可以发现,其实4次计算可以缩减为两次
  • 分:如果n是偶数,将 X^n 分成两个 X^n/2 相乘;如果n是奇数,将 X^n 分成 X^(n-1/2) * X^(n-1/2) * X
  • 治:递归计算分出来的值。
  • 合:合并计算结果。
时间复杂度: T(n) = 2(n/2) + θ(1) ,根据主方法(2)得出解为: T(n) = log n

斐波那契数

目标:根据斐波那契数定义,即, F0 = 0,F1=1,Fn=Fn-1 + Fn-2 (n大于等于2),算出第n个的值。
原始方式:递归计算,即直接根据定义计算, Fn-1 和 Fn-2 ,Fn-1和Fn-2再根据定义向下计算。时间复杂度(指数级别):T(n) = (φ) ⁿ 其中 φ = (1+ √5)/2 即黄金比例,该值大于1。
原始方式时间复杂度的大概证明:简单画了个递归树图,如下,可以看到,从根节点出发,每次分了两个节点出来。设高为h,因此叶节点数为, 2^h ,那么h的值是多少?我们知道,可以发现 h >= n/2 ,因此 T(n) >= 2 ^ (n/2) ,这个数基本接近 T(n) = (φ) ⁿ
优化1:从递归树可以发现,很多子树是重复的,没有必要重复计算,但是要得到k项值,又必须知道k-1项和k-2项的值。那么,我们换一种思路,假设计算第k项钱,k-1项和k-2项我们已经知道了呢?那么计算k项只需要一次相加。而我们只要从头算起,就可以在计算k项值前知道k-1项和k-2项值。即,计算 F0,F1,F2,F3…Fn 从而得到Fn,时间复杂度为 T(n) = θ(n)。
优化2:通过定理(数学归纳法得到),转化为2阶矩阵乘法来得到。

    Fn+1  Fn				    1     1
(                    )  =  (                      ) ^n                  
    Fn    Fn-1                  1     0   

你可能感兴趣的:(笔记,算法)