zoukankan      html  css  js  c++  java
  • 算法时间复杂度的计算

    在我们编程的过程中,可能会遇到这样的情况。(下面只是一个小小的例子,现实中不会这么简单,这里只是取到一个抛砖引玉的作用哈)

    计算1-100的和:1+2+3+... ...+100

    或者我们直接升级,计算1到n的和:1+2+3+... ...+n

    我们不会能那个计算机搁哪儿摁,对不。我们写程序实现之。

    那么我们在程序中应该怎样去实现了

    有的人可能会这样写:

    $a=0;
    for ($i=1;$i<=n;$i++){
    $a+=$i;
    }
    echo $a;

    这样的写法确实能达到效果,但是当我们的n特别大时,会发生生么样的情况呢?答案是:会发生以下情况(n=100000000000)

    计算机没有办法处理这么大的数字。

    我们这里就可以引入一个时间复杂度的概念了。

    时间复杂度就是

    一个算法执行所耗费的时间,从理论上是不能算出来的,必须上机运行测试才能知道。但我们不可能也没有必要对每个算法都上机测试,只需知道哪个算法花费的时间多,哪个算法花费的时间少就可以了。并且一个算法花费的时间与算法中语句的执行次数成正比例,哪个算法中语句执行次数多,它花费时间就多。一个算法中的语句执行次数称为语句频度或时间频度。记为T(n)。算法的时间复杂度是指执行算法所需要的计算工作量。

    我们上面的算法的时间复杂度为T(n) = O(n)

    而有的人会这样改写上面的算法

    $n = 100000000000;
    $a = $n+($n*($n-1)/2);
    echo $a;

    这样写的结果就是:秒算出来结果

    要不要科学计算法可以自己设置的哈。

    那为什么下面的这个算法会运行的这么快呢?

    因为它只做一次计算,时间复杂度为T(n) = O(1)

    通过这个例子,大家应该对时间复杂度有了一个比较入门的印象了。

    下面我们来说说具体应该怎样去计算一个算法的时间复杂度。

    比如我们有如下算法:

    i=1; k=0
    while(i<n)
    { k=k+10*i;i++;
    }
    其中while语句会执行n-1次,所以它的时间复杂度为T(n) = n-1; T(n)=O(n)
    如果一个算法的执行次数是 T(n),那么只保留最高次项,同时忽略最高项的系数后得到函数 f(n),此时算法的时间复杂度就是 O(f(n))
    我们知道常数项对函数的增长速度影响并不大,所以当 T(n) = c,c 为一个常数的时候,我们说这个算法的时间复杂度为 O(1);如果 T(n) 不等于一个常数项时,直接将常数项省略。所以上面例子的时间复杂度为T(n)=O(n)。
     
     
    对于多个循环
    for(int i = 0; i < n; i++) { // 循环次数为 n
      for(int j = 0; j < n; j++) { // 循环次数为 n
        printf("Hello, World! "); // 循环体时间复杂度为 O(1)
      }
    }
    此时时间复杂度为 O(n × n × 1),即 O(n^2)。

    对于顺序执行的语句或者算法,总的时间复杂度等于其中最大的时间复杂度。

    // 第一部分时间复杂度为 O(n^2)
    for(int i = 0; i < n; i++) {
      for(int j = 0; j < n; j++) {
      printf("Hello, World! ");
       }
    }
    // 第二部分时间复杂度为 O(n)
    for(int j = 0; j < n; j++) {
      printf("Hello, World! ");
       }
    此时时间复杂度为 max(O(n^2), O(n)),即 O(n^2)。

    下面我们来一个进阶一点的:
    void aFunc(int n) {
        for (int i = 2; i < n; i++) {
            i *= 2;
            printf("%i
    ", i);
        }
    }
    我们需要计算上述算法的时间复杂度,是不是看的有点懵,放轻松,我们一步步分析。
    假设循环次数为 t,则循环条件满足 2^t < n。
    可以得出,执行次数t = log(2)(n),即 T(n) = log(2)(n),可见时间复杂度为 O(log(2)(n)),即 O(log n)。

    再次进阶
    long aFunc(int n) {
        if (n <= 1) {
            return 1;
        } else {
            return aFunc(n - 1) + aFunc(n - 2);
        }
    }

    是不是更懵了,下面我们来分析:
    显然运行次数,T(0) = T(1) = 1,同时 T(n) = T(n - 1) + T(n - 2) + 1,这里的 1 是其中的加法算一次执行。
    显然 T(n) = T(n - 1) + T(n - 2) 是一个斐波那契数列,通过归纳证明法可以证明,当 n >= 1 时 T(n) < (5/3)^n,同时当 n > 4 时 T(n) >= (3/2)^n。
    所以该方法的时间复杂度可以表示为 O((5/3)^n),简化后为 O(2^n)。
     
    一般时间复杂度的排序为:
    Ο(1)<Ο(log2n)<Ο(n)<Ο(nlog2n)<Ο(n2)<Ο(n3)<…<Ο(2n)<Ο(n!)
    在编程中我们算法的时间复杂度越小越好哈!
    其实复杂度分为:时间复杂度和空间复杂度,不做任何说明的情况下算法的复杂度为时间复杂度。
     
     
     


     
  • 相关阅读:
    [BAT] 通过批处理删除7天前的报告,并删除当前目录下的空文件夹
    Codeforces Round #361 (Div. 2) A
    Codeforces Round #359 (Div. 2) C
    Codeforces Round #359 (Div. 2) B
    Codeforces Round #359 (Div. 2) A
    Codeforces Round #357 (Div. 2) C
    Codeforces Round #357 (Div. 2) B
    Codeforces Round #357 (Div. 2) A
    Codeforces Round #356 (Div. 2) C
    Codeforces Round #356 (Div. 2) B
  • 原文地址:https://www.cnblogs.com/573734817pc/p/10109312.html
Copyright © 2011-2022 走看看