Warning: Undefined array key "HTTP_ACCEPT_LANGUAGE" in /www/wwwroot/blog/wp-content/plugins/UEditor-KityFormula-for-wordpress/main.php on line 13
【算法设计与分析】概述(三)— – Machine World

【背景】

        在概述(二)中,我们着重介绍了对O的分析,事实上还有很多关于复杂度的分析,以及重要结论,但眼下无论是工业界或是学界都着重分析O,篇幅有限我们在概述(二)中点到即止,详细的分析法还请查阅《计算机程序设计艺术》,本文针对O的分析回顾一下中学数学基础,方便今后对时间复杂度进行分析。

【标准记号与常用函数】

单调函数

单调递增:

mnf(m)f(n)

单调递减:

mnf(m)f(n)

严格单调递增:

m<nf(m)<f(n)

严格单调递减:

m<nf(m)>f(n)

取整函数

向下取整:

x

向上取整:

x

取整函数若干性质

  • x1<xxx<x+1

  • n/2+n/2=n

  • 对于n0,a,b>0有:

n/a/b=n/ab

n/a/b=n/ab

a/b leq(a+(b1))/b

a/b(a(b1))/b

f(x)=x,g(x)=x

多项式函数

  • p(n)=a0+a1n+a2n2++adnd;ad>0
  • p(n)=Θ(nd)
  • f(n)=O(nk)f(n)
  • f(n)=O(1)f(n)c
  • kdp(n)=O(nk)
  • kdp(n)=Ω(nk)
  • k>dp(n)=o(nk)
  • k<dp(n)=ω(nk)

指数函数

对于正整数m,n和实数a > 0

  • a0=1
  • a1=a
  • a1=1a
  • (am)n=amn
  • (am)m=(an)m
  • aman=an+m
  • a>1an
  • a>1limnnban=0nb=o(an)
  • ex=1+x+x22!+x33!+=i=0xii!
  • ex1+x
  • |x|11+xex1+x+x2
  • limn(1+xn)n=ex

对数函数

  • logn=log2n
  • lgn=log10n
  • lnn=logen
  • logkn=(logn)k
  • loglogn=log(logn)

对所有实数a>0,b>0,c>0,n有:

  • a=blogba
  • logc(ab)=logca+logcb
  • logban=nlogba
  • logba=logcalogcb
  • logb(1/a)=logba
  • logba=1logab
  • alogbc=clogba
  • |x|1ln(1+x)=xx22+x33x44+x55++(1)n1xnn
  • forx>1,x1+xln(1+x)x
  • foranya>0,limnlogbn(2a)logn=limnlogbnna=0logbn=o(na)

阶乘函数

n!={1n=1n(n1)!n>0

Stirling's approximation:

n!=2πn(ne)n(1+Θ(1n))

  • n!=o(nn)
  • n!=ω(2n)
  • log(n!)=Ω(nlogn)
  • n!=2πn(ne)neαn112n+1<αn<112n

【数列求和公式】

等差数列求和:

Sn=(a1+an)n2=na1+n(n1)2d

等比数列求和:

Sn=a1(1qn)1q=a1anq1q(q0)

【非递归算法复杂性分析】

基础:

(1) for/while循环

    循环体内计算时间*循环次数;

(2) 嵌套循环

    循环体内计算时间*所有循环次数;

(3) 顺序语句

    各语句计算时间相加;

(4) if-else语句

    if语句计算时间和else语句计算时间的较大者。

一般步骤:

1. 决定用哪个(或哪些)参数作为算法问题规模的度量

    可以从问题的描述中得到。

2. 找出算法中的基本语句

    通常是最内层循环的循环体。

3. 检查基本语句的执行次数是否只依赖于问题规模

    如果基本语句的执行次数还依赖于其他一些特性,则需要分别研究最好情况、最坏情况和平均情况的效率。

4. 建立基本语句执行次数的求和表达式

    计算基本语句执行的次数,建立一个代表算法运行时间的求和表达式。

5. 用渐进符号表示这个求和表达式

    计算基本语句执行次数的数量级,用大O符号来描述算法增长率的上限。

例子:

1
2
3
4
5
6
int m = 0, i, j;
for(i = 1; i <= n; i++){
    for(j = 2*i; j <=n; j++){
        m++;
    }
}

解法1:算法的基本操作为:m++m的初值为0, m的值即为执行次数.由于内循环从2nn,所以i的最大值满足2in,即in/2:

m=i=1n/2j=2in1=i=1n/2(n2i+1)=nn22i=1n/2+n2=n22n2(n2+1)+n2=n44

解法2:n为偶数, 外循环执行n/2次. 外循环i=1时, 内循环j2变到n, 语句m++执行n1次; i=2时, 内循环执行n3次; ……; i=n/2时, 内循环执行1次.

故:

m=(n1)+(n3)++3+1=n24

即:

T(n)=O(n2)

【递归算法复杂性分析】

基础:

对递归算法时间复杂性的分析, 关键是根据递归过程建立递推关系式, 然后求解这个递推关系式》

例1:

1
2
3
4
int factorial(int n){
    if(n == 0) return 1;
    return n * factorial(n-1);
}

可得递推式:

T(n)={1n=0T(n1)+1n>0

解之:

T(n)=n

例2:

1
2
3
4
5
6
7
8
9
void Hanoi(int n, char A, char B, char C){
    if(n == 1){
        printf("A->C");
    }else{
        Hanoi(n-1, A, C, B);
        printf("A->C");
        Hanoi(n-1, B, A, C);
    }
}

可得递推式:

T(n)={1n=12T(n1)+1

解之:

T(n)=2T(n1)+1=2(2T(n2)+1)+1=22Tn2+(2+1)==2n1+2n2++22+2+1=2n1=O(2n)

扩展递归

扩展递归(extended recusion)是一种常用的求解递推关系式的基本技术,扩展就是将递推关系式中等式右边的项根据递推式进行替换,扩展后的项被再次扩展,依次下去,会得到一个求和表达式,然后可以借助求和技术进行求解。

例:求解下述递推式时间复杂性:

T(n)={7n=12T(n/2)+5n2n>1

解:

简单起见:设n=2k,将递推式进行扩展:

T(n)=2T(n/2)+5n5=2(2T(n/4)+5(n/2)2)+5n2==2kT(1)+2k1×5(fracn2k1)2++2×5(n2)2+5n2=7n+5i=0k1(n2)(2i)=7n+5n2(212k1)=10n23n10n2=O(n2)

【概述小结】

算法与程序

  1. 算法基本概念和性质

  2. 算法描述方法

问题求解过程

算法复杂性分析

  1. 算法复杂性基本概念

  2. 算法复杂性的渐近性态

  3. 算法渐近分析记号的定义和性质

  4. 非递归算法和递归算法的复杂性分析

【参考文献】

  • 2019年广西师范大学计算机与信息工程学院算法设计与分析课件[OL].李志欣教授.2019.01.01

作者 WellLee

在 “【算法设计与分析】概述(三)— <分析基础>” 有 1 条评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注