zoukankan      html  css  js  c++  java
  • 数据结构与算法复习——2、递归分析入门

    2、递归分析入门

    一、引例

      上一篇介绍的最长子序列和问题的分治算法的分析中,提出了一个递推式,我们没有求解该递推式的上界。实际上,我们经常在递归算法的分析里遇到递推式,很显然这是由于递归本身的结构决定的。这一篇我们就简单地介绍一下怎么做分治算法下的递归分析。实际上递归有多种情况,除了分治算法,比较常见的还有搜索,这就不在本篇的讨论范围之内。

      在分析分治算法之前,先来分析一个不太“优”的递归算法。看下面的求解斐波那契数列第$N$项的算法:

    1 int Fib(int N) {
    2     if (N == 0 || N == 1)
    3         return 1;
    4     return Fib(N - 1) + Fib(N - 2);
    5 }
    Fibonacci

     这个算法经常被当作递归的“反面教材”,因为它的冗余递归太多:求解$Fib(N-1)$时,实际上已经求了$Fib(N-2)$,可是后面又调用了一次。这个算法有多坏呢?我们建立下面的关于这个算法时间上界的递推式:

    $T(0)=T(1)=1$

    $T(N)=T(N-1)+T(N-2)$

    可以很容易就发现$T(N)=Fib_N$,也就是时间以斐波那契数列级增长。斐波那契数列有很多研究,譬如前后两项之比的极限是黄金分割比$Phi = frac{sqrt{5}+1}{2}$,这告诉我们这个算法的时间是指数级增长!指数增长一般是难以忍受的,常见情况里仅快于阶乘增长。可见上面这个算法有多差。

      上面的分析已经告诉了我们怎么做递归分析,就是求其时间上界数列的递推式,从递推式里求解通项公式或者至少知道增长等级。这个算法一旦优化就不适合递归了,因此这里就不对它进行优化了。下面我们分析一个经典的分治递归算法。

    二、归并排序分析

      排序算法是非常重要而基础的,我们有好多种排序算法,而不管怎么考虑,归并排序都一定是其中最经典的之一。简要来说,归并排序的思路是这样的:递归地求解,假设我们已经有了两个排好序的$N$项序列,把它们合并成$2N$项的有序序列就好了。至于这两个序列的来源,我们可以把它们等分成两部分,让这两部分是各自排好序的,然后合并;可见这个过程应该递归下去。这个递归当然有基本情况:$N=1$时,无需再分即有序。归并排序的主算法可以这样实现:

    1 void merge_Sort(int A[], int l, int r) {
    2     if (r - l > 1) {
    3         merge_Sort(A, l, (l + r) / 2);  //分治
    4         merge_Sort(A, (l + r) / 2, r);
    5     }
    6     _merge_sort(A, l, (l + r) / 2, r);  //归并
    7     return;
    8 }
    merge sort

    其中第6行的归并函数的某种实现方式如下:

     1 int tempL[MXN], tempR[MXN];  //归并排序的临时数组
     2 
     3 void _merge_sort(int A[], int l, int mid, int r) {  //归并步骤
     4     for (int i = l; i < mid; i++) tempL[i - l] = A[i];  //将两侧的数记入临时数组
     5     for (int j = mid; j < r; j++) tempR[j - mid] = A[j];
     6     tempL[mid - l] = tempR[r - mid] = 0x7fffffff;
     7     int cnt = l, i = 0, j = 0;
     8     for (; l + i < mid && mid + j < r;cnt++) {  //比较归并
     9         if (tempL[i] <= tempR[j]) A[cnt] = tempL[i++];
    10         else A[cnt] = tempR[j++];
    11     }
    12     while (l + i < mid) A[cnt++] = tempL[i++];  //余项归并
    13     while (mid + j < r) A[cnt++] = tempR[j++];
    14     return;
    15 }
    merge

    当然归并排序的主算法和归并函数有很多种实现和优化的方式,这里就不展开了,但是总之,归并函数的时间复杂度上界不可能低于$O(N)$。

    下面我们就可以来分析归并排序的时间复杂度。根据主算法,写出它的时间上界的递推式:

    $T(N) = 2T(N/2) + N$

    为了方便分析,我们首先假设:$N = 2^k$,这样$N/2$就有一直都是有意义的。这种情况下,我们有两种处理方式:

    1、做这样的变换:

    $frac{T(N)}{N} = frac{T(N/2)}{N/2} + 1$

    可见${ frac{T(2^k)}{2^k} }$是一个关于$k$的等差数列,又由于$frac{T(1)}{1} = 1$,我们就可以求出:

    $frac{T(N)}{N} = k + 1 = log N + 1$

    $T(N) = N log N + N = O(N log N)$

    这是第一种分析方法。

    2、第二种分析方法比较“暴力”:有下面两个式子:

    $T(N) = 2T(N/2) + N$

    $T(N/2)=2T(N/4)+N/2$

    代入得:

    $T(N) = 4T(N/4)+2N$

    不断代入,直到最后得到:

    $T(N) = 2^k T(1) + kN = N + N log N = O(N log N)$

    这就是第二种分析方法。

    上面我们假设了$N=2^k$,如果不是这样的呢?通过刚刚的分析我们知道,只要$N = p2^k$,我们就可以把求解$T(N)$转化成求解$T(p)$,因此我们下面只分析奇数的情况。

    为了得到相同的结论,我们设$N = 2^k + m, 0 leq m < 2^k$,做数学归纳法:

    1°  首先,$k=0$的特殊情况,我们有$T(1) = 1$;$k = 1$时,我们有

    $T(2) = 2T(1) + 2 = 4 = N log N + N$、$T(3) = T(1)+T(2) + 3 = 8 = N log N + N$

    (当$log N$不是整数时我们向上取整,下面我们将看到最后一个约等号写成等号是不影响上界的,因为$2$是$2$的幂,它的$log N$不需要向上取整,但统一向上取整仍得到一个上界);

    2°  然后归纳假设对$0 leq k < n$,对任意的$m$,都成立$T(N) = N log N + N$,那么在$N = n = 2^n + m$时($m$仍然是任意的):

    若$m$是偶数,我们就有:$T(N) = 2T(2^{n-1} + m/2) + N$,根据归纳假设就有:

    $T(N) = 2[n(2^{n-1}+m/2) + 2^{n-1} + m/2] + N$

    $=(n + 1)(2^n + m) + N$

    $=(n + 1)N + N = N log N + N$

    若$m$是奇数,不妨设$m = 2q+1$,则有$T(N) = T(2^{n-1} + q) + T(2^{n-1}+q+1) + N$,根据归纳假设就有:

    $T(N) = n(2^{n-1}+q) + 2^{n-1} + q + n(2^{n-1} + q + 1) + 2^{n-1} + q + 1 +N$

    $=n(2^n + 2q + 1) + 2^n +2q + 1 + N$

    $=(n + 1)N + N = N log N + N$

    至此根据数学归纳法原理,得证$T(N) = N log N + N = O(N log N)$。

    以上就是解决分治算法的时间复杂度的思路。可以看到如果除了分治步骤,其余的步骤是$O(N)$的话,一般就会成为$O(N log N)$。如果不是,则要另行分析。

  • 相关阅读:
    Unix命令大全
    vs2008 与 IE8出现的兼容性问题
    Java 创建文件、文件夹以及临时文件
    如何修改Wamp中mysql默认空密码
    PAT 乙级真题 1003.数素数
    Tags support in htmlText flash as3
    DelphiXE4 FireMonkey 试玩记录,开发IOS应用 还是移植
    10 Great iphone App Review sites to Promote your Apps!
    HTML tags in textfield
    Delphi XE4 IOS 开发, "No eligible applications were found“
  • 原文地址:https://www.cnblogs.com/halifuda/p/14336067.html
Copyright © 2011-2022 走看看