【数据结构】时间复杂度和空间复杂度计算

时间复杂度AND空间复杂度专项

本文参考:https://www.cnblogs.com/coder-programming/p/11093608.html

时间维度:是指执行当前算法所消耗的时间,我们通常用「时间复杂度」来描述。
空间维度:是指执行当前算法需要占用多少内存空间,我们通常用「空间复杂度」来描述。

时间复杂度

一个算法花费的时间与算法中语句的执行次数成正比例,哪个算法中语句执行次数多,它花费时间就多。 一个算法中的语句执行次数称为语句频度或时间频度。记为 T(n)。

常见的算法时间复杂度由小到大依次为:Ο(1)<Ο(log2n)<Ο(n)<Ο(nlog2n)<Ο(n2)<Ο(n3)<Ο(nk)<Ο(2n) ,随着问题规模 n 的不断增大,上述时间复杂度不断增大,算法的执行效率越低

常见的时间复杂度:

常见的时间复杂度:

常数阶 O(1)

对数阶 O(log2n)

线性阶 O(n)

线性对数阶 O(nlog2n)

平方阶 O(n^2)

立方阶 O(n^3)

k 次方阶 O(n^k)

指数阶 O(2^n)

常见阶数串讲

  • 常数阶 O(1)

    • 没有循环结构,代码上万行都可以,消耗并不伴随某个的增长而增长,都是O(1)
  • 对数阶O(log2n)

    • 举个例子
    int n=1000;
    
    int i=1;
    
    while(i<=n){
        i=i*2;
    }
    
    cout<<"啦啦啦啦i="<<i<<endl;
    

    看在while循环中执行了多少次:while终止条件是i>n的时候,即当2的x次方等于n时结束循环,那么显然x=log2n。也就是说while循环执行了log2n次后就结束了,那么这个算法的时间复杂度就是log2n。

    从这个例子可以看出,如果将循环改成

    i=i*3;
    

    那么复杂度自然就变成了log3n。

  • 线性阶O(n)

    现在你已经基本入门啦,我们直接上例子,线性阶很好理解,就是在循环中变量增长从倍数变成了单个增长。

    int n=1000;
    
    int i=1;
    
    while(i<=n){
        i++;
    }
    
    cout<<"啦啦啦啦i="<<i<<endl;
    

    显然i需要增加n次才可以执行结束,故时间复杂度为O(n)

  • 线性对数阶O(nlogN)

    套娃!外层循环执行n次,内部循环需要执行logN次,那么一共就是n*logN啦,故时间复杂度为O(nlogN)。

    继续上代码:

    int j=0;
    
    for(int i=1;i<=n;i++){
        j=1;
        while(j<n){
            j=j*2;//时间复杂度为O(log2n)
        }
    }
    

    这个时间复杂度就是O(nlog2n)

  • 平方阶O(n²)

    平方阶和线性对数阶类似,也是套娃!

    外层n,内层n不就成n²了吗!

    如果外层m,内层n,那么就是O(mn)

  • 立方阶O(n³)、K次方阶O(n^k)

    类似~

运算法则

以上举例都是套娃或者单个循环的,如果遇到多个怎么办?这就涉及到时间复杂度计算法则了:

只关注循环执行次数最多的一段代码

加法法则:总复杂度等于量级最大的那段代码的复杂度
如果 T1(n)=O(f(n)),T2(n)=O(g(n));那么 T(n)=T1(n)+T2(n)=max(O(f(n)), O(g(n))) =O(max(f(n), g(n))).

乘法法则:嵌套代码的复杂度等于嵌套内外代码复杂度的乘积
T(n) = T1(n) * T2(n) = O(n*n) = O(n2)

平均时间复杂度和最坏时间复杂度

  • 平均时间复杂度:所有可能输入实例均以等概率出现的情况下,该算法的运行时间。
  • 最坏时间复杂度:最坏情况下(即算法运行时间最长的情况)
  • 平均时间复杂度与最坏时间复杂度是否一致,与算法有关。

排序算法时间复杂度与空间复杂度

空间复杂度

类似于时间复杂度,一个算法的空间复杂度定义为该算法所耗费的存储空间,也是问题规模n的函数

(别问,上面一句话我没看懂。。。)

可以理解为,空间复杂度是用来评判一个算法的执行所需占用的临时存储空间。在做算法分析的时候,主要讨论的是时间复杂度。从用户体验上看,更看重程序的执行速度,所以有时候为了提升算法速度使用空间来换时间。

突然想到那种变态排序,1~2015范围,直接开辟2016的数组大小,有数的就标记为1其余为0,然后遍历输出。。。时间复杂度:O(n)

定义

算法的空间复杂度的计算公式记作:S(n)=O(f(n)),其中,n为问题的规模,f(n)为语句关于n所占存储空间的函数。

举个例子:

void print(int n) {
  int i = 0;//常量阶,不算问题规模
  int[] a = new int[n];//规模为n
  for (i; i <n; ++i) {
    a[i] = i * i;
  }

  for (i = n-1; i >= 0; --i) {
    print out a[i]
  }
}

显然代码开辟了一个规模为n的数组,故整体的空间复杂度为O(n)

posted @ 2020-09-19 20:33  巴塞罗那的余晖  阅读(1492)  评论(0编辑  收藏  举报
//雪花飘落效果