一篇文章搞懂时间复杂度

    由于时间复杂度是为了表达在大规模下基础操作的执行次数,因此当获得关于问题规模n的函数 f(n) 时,我们只关注最高次幂,并且忽略其系数,因为这些值在大规模问题下并不能对其时间变化产生明显影响。如,f(n)=3n^{3}+4n^{2}+5,这里我们将忽略常数项,低次幂以及n^{3}的系数3,获得时间复杂度为O(n^{3})

    计算时间复杂度有2种方法,一种是根据直观的循环结构来计算,另一种是根据基础操作来推算。以下,分别阐述:

一.直观计算

public static void fc(int N)
{
    int sum = 0;
    for (int i = 1; i < N; i *= 2) { // 循环n次
        for (int j = 0; j < N; j++) { // 循环n次
            sum++;
        }
    }
    System.out.println(sum);
}

上述代码共有2层循环,嵌套循环遵循乘法原则,所以时间复杂度为O(n^2)

二.规模计算

public static void fb(int N)
{
    int sum = 0;
    for (int i = 1; i < N; i *= 2) {
        for (int j = 0; j < i; j++) {
            sum++;
        }
    }
    System.out.println(sum);
}

外层循环很容易看出是log_{2}n,但内层循环 j 是根据外层循环 i 的值变化的,无法直观计算,此时就需要根据问题规模来算时间复杂度。

先找到基础操作sum++,可以看出,当 i=1 时,sum++执行1次,当 i=2 时,sum++执行2次,当 i=4 时,sum++执行4次,...,当 i=N 时,sum++执行N次。根据加法原则,sum++总共执行次数应为,1+2+4+...+N次,根据等比数列求和公式 S_{n}=\frac{a_{1}-a_{n}q}{1-q}=\frac{a_{1}(1-q^{n}))}{1-q}(q\neq 1) ,根据公式得出执行次数总和 S_{n}=2^{n}-1 (n为项数),又因为n和N的关系可以有如下表示:2^{n-1}=N,整理得n=log_{2}N+1,将n和N的关系等式代入S_{n}中得出结果S_{n}=2N-1,因此得到时间复杂度为O(N)。

三.练习题

1.分析以下算法的时间复杂度

void fun(int n)
{
    int i=0,s=0;
    while(s<n){
        ++i;
        s=s+i;
    }
}

答案:

i 的值随着循环次数增加,逐渐递增为1,2,3,4...,m

s的值实际为 i 的所有取值的总和,所以当i=m时,s=\frac{(1+m)*m}{2},由于循环条件为s<n,因此在循环第m次时,s+k(假设的一个常量)=n,即为\frac{(1+m)*m}{2}+k=n

求根公式:ax^{2}+bx+c=0(a\neq 0) => x=\frac{-b\pm \sqrt{b^{2}-4ac}}{2a}

由求根公式得,m=\frac{-1+\sqrt{1-8k+8n}}{2},即f(n)=\frac{-1+\sqrt{1-8k+8n}}{2}

去掉常数项和n的系数,得出时间复杂度T(n)=O(\sqrt{n})

2.求最后一行的语句频度在最坏的情况下是多少。

for(i=n-1;i>=1;--i)
    for(j=1;j<=i;++j)
        if(A[j]>A[j+1]) A[j]与A[j+1]对换;

答案:

内层循环次数随着 i 的变化而变化,i=n-1时,内层循环n-1次;i=n-2时,j循环n-2次;...;i=2时,j循环2次;i=1时,j循环1次。(n-1,n-2,n-3,...,2,1)

根据加法原则,内层循环总次数的和为,\frac{(1+n-1)(n-1)}{2},整理得,\frac{n^{2}-n}{2}

去掉低次幂及高次幂的系数,得到时间复杂度,T(n)=O(n^{2})

3.如下函数mergesort()执行的时间复杂度为多少?假设函数调用被写为mergesort(1,n),函数merge()的时间复杂度为O(n)。

void mergesort(int i,int j)
{
    int m;
    if(i!=j){
        m=(i+j)/2; // O(1)
        mergesort(i,m);
        mergesort(m+1,j);
        merge(i,j,m); // O(n)
    }
}

答案:

因为m为 i,j 的平均数,可以得出,T(n)=O(1)+2*O(\frac{n}{2})+O(n)

即 f(n)=2f(\frac{n}{2})+n

             =2*(2*f(\frac{\frac{n}{2}}{2})+\frac{n}{2})+n=2^{2}*f(\frac{n}{4})+2n

             =2^{3}*f(\frac{n}{8})+3n

             ...

             =2^{k}*f(\frac{n}{2^{k}})+kn

又因为f(1)=1,当n=2^{k}(k=log_{2}n) 时,为最终时刻,即为f(1)的时候,

代入得f(n)=n+nlog_{2}n

所以时间复杂度为,T(n)=nlog_{2}n

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值