美文网首页
时间复杂度和空间复杂度笔记

时间复杂度和空间复杂度笔记

作者: jianshu_无崖子 | 来源:发表于2018-11-25 23:33 被阅读0次
    1.jpeg

    复杂度分析笔记

    复杂度主要分为时间和空间复杂度

    时间复杂度:算法(程序)执行的时间变化趋势

    空间复杂度:算法(程序)执行的内存空间使用量

    复杂度分析,不是通过工具测量计算出来的,而是估量算法运行所要消耗的时间

    通过代码来练习代码复杂度分析

    int cal(int n){
        int sum = 0;
        int i = 1
        for(; i < n; i++){
            sum = sum + i;
        }
        return sum;
    }
    

    假设每行代码的执行时间都是一样的,unit_time;

    再来看这段代码:

    第2,3行只执行了一遍,需要时间为2*unit_time

    第4,5行执行了n+n编,需要时间为2n*unit_time

    所以这段代码需要的总时间T(n) = (2n + 2) * unit_time

    再看如下这段代码

    int cal(int n){
        int sum = 0;
        int i = 1;
        int j = 1;
        for(;i<n;i++){
            for(;j<n;j++){
                sum = sum + i*j;
            }
        }
        return sum;
    }
    

    第2,3,4行执行了一遍 3*unit_time

    第5行,执行了n遍,n*unit_time

    第6,7行,2n^2

    所以这段代码需要的总时间为T(n) = (3+n+2n^2)*unit_time

    可以看出来所有的代码的执行时间和每行代码执行的次数成正比

    T(n) = O(f(n))

    其中的f(n)为代码执行次数的函数

    O(n)函数表示代码执行时间与代码执行次数f(n)成正比

    这种方法称为大O表示法,并不表示算法执行的具体时间,而是表示随着数据规模增长的变化趋势

    随着数据规模不断增大,常数对对时间的影响可以忽略不记

    所以上面的两个时间复杂度可以表示为O(n) O(n^2)

    时间复杂度分析的几种方法

    1.只关注循环 次数最多的那一段代码:

    int cal(int n){
        int sum = 0;
        int i = 1
        for(; i < n; i++){
            sum = sum + i;
        }
        return sum;
    }
    

    如同上面举过的例子

    这里执行次数最多的是第4,5行,其它行数为常数,可以忽略不记,所以这段代码的时间复杂度为O(n)

    2.加法法则:总的复杂度等于量级最大的那段代码的复杂度

    int cal(int n) { 
        int sum_1 = 0 ;
        int i = 1;
        for(;i < n; i++){
            sum_1 = sum_1 + i;
        }
        
        int sum_2 = 0;
        int j = 1;
        for(;i < n; i++){
            for(;j < n; j++){
                sum_2 = sum_2 + i*j;
            }
        }
        return sum_1 + sum_2;
    }
    
    

    可以把这段代码分为两部分来看

    第一部分 时间复杂度为O(n)

    第二部分时间复杂度为O(n^2)

    总的时间复杂度,我们取那个最大的,所以时间复杂度为O(n^2)

    换算为公式:T(n) = max(O(f(n)),O(g(n)));

    3.乘法法则:嵌套代码的复杂度等于嵌套内外代码复杂度的乘积

    int cal(int n){
        int sum = 0;
        int i = 1;
        for(;i < n; i++){
           sum = sum + f(i);
        }
        return sum;
    }
    
    int f(int n){
        int sum = 0;
        int i = 1;
        for(;i < n; i++){
            sum = sum + i;
        }
        return sum;
    }
    

    上面这段代码,如果f(n)是一段普通的操作,则时间复杂度为O(n)

    但是,f(n)不是一份简单的操作,他是一段函数 ,所以总的时间复杂度

    T(n) = O(n) * O(n) = O(n^2

    需要注意的几点

    1.O(1)

    O(1)表示时间复杂度为常量,并不是说只有一行代码。即使代码有成千上万行,只要是常数,就记为O(1)

    int i = 0;
    int j = 1;
    sum = i + j;
    

    上面那段代码为O(1)而不是O(3)

    2.O(logn) O(nlogn)

    int i = 1;
    while( i <= n){
        i = i * 2;
    }
    

    计算上述代码的时间复杂度,关键是计算出来代码执行的次数

    2^x = n 所以x = log2 n

    所以上述时间复杂度为O(log2n)

    采用大O计数法,忽略次数,记为O(logn)

    3.O(m + n) O(m * n)

    int cal(int m, int n) {
      int sum_1 = 0;
      int i = 1;
      for (; i < m; ++i) {
        sum_1 = sum_1 + i;
      }
    
      int sum_2 = 0;
      int j = 1;
      for (; j < n; ++j) {
        sum_2 = sum_2 + j;
      }
    
      return sum_1 + sum_2;
    }
    

    上述代码,因为m,n的值未知,不清楚谁大谁小,不能省略其中的一个,无法使用加法法则

    时间复杂度为O(m + n),

    可以使用乘法法则:O(m * n )

    空间复杂度分析

    void print(int n) {
      int i = 0;
      int[] a = new int[n];
      for (i; i <n; ++i) {
        a[i] = i * i;
      }
    
      for (i = n-1; i >= 0; --i) {
        print out a[i]
      }
    }
    
    

    可以看到上述代码:

    只有在第3行的时候才使用了n大小的数组,其余地方都没有使用多余的空间,所以这段代码的空间复杂度为O(n).

    相关文章

      网友评论

          本文标题:时间复杂度和空间复杂度笔记

          本文链接:https://www.haomeiwen.com/subject/yhtvqqtx.html