关于Big-O表示法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/freedom12354/article/details/82119782

知道算法的时间复杂度和空间复杂度能让你针对具体度的业务选择正确的算法。

一、时间复杂度

1、概述

一般情况下,算法的基本操作重复执行的次数是模块n的某一函数f(n),因此,算法的时间复杂度记做 T(n) = O(f(n))。 随着模块n的增大,算法执行的时间增长率f(n)的增长率成正比,所以f(n)越小,算法的时间复杂度越低,算法的效率越高。

int num = 0; // 第一次执行
int n = 7;

for (int i = 0; i < n; i ++) { // 执行了n次
    num += 1;
}

这个算法执行了 1 + n 次,如果n无限大,我们可以把前边的1忽略,也就是说这个算法执行了n次。时间复杂度常用大O符号表示,这个算法的时间复杂度就是O(n),我们称之为大O记法。 

而判断一个算法的效率时,函数中的常数和其他次要项常常可以忽略,而更应该关注主项(最高项)的阶数。如:算法A需要运行2n^2+3n+1次,其中的3n+1已经没法和2n^2的结果相比较,最终几乎可以忽略不计。

2、时间复杂度的推导

在一个算法中:

一个算法所耗费的时间=算法中每条语句的执行时间之和;

每条语句的执行时间=语句的执行次数(即频度(Frequency Count))×语句执行一次所需时间;

算法转换为程序后,每条语句执行一次所需的时间取决于机器的指令性能、速度以及编译所产生的代码质量等难以确定的因素。

若要独立于机器的软、硬件系统来分析算法的时间耗费,则设每条语句执行一次所需的时间均是单位时间,一个算法的时间耗费就是该算法中所有语句的频度之和

推导大O阶:

1.用常数1来取代运行时间中所有加法常数。 

2.修改后的运行次数函数中,只保留最高阶项 

3.如果最高阶项存在且不是1,则去除与这个项相乘的常数。

得到的最后结果就是大O阶

如:

int i ,j ,k;
int n = 100;
int aa[n][n], bb[n][n],cc[n][n];
    
for(i =0; i < n; i++) { //n
    for (j = 0; j < n; j++) { //n*n
        aa[i][j] = 0; //n²
        for (k = 0; k < n; k++) {//n²*n
            aa[i][j] = aa[i][j] + bb[i][k] * cc[k][j];//n³
        }
    }
}

该算法中所有语句的频度之和(即算法的时间耗费)为:

T(n)=^{^{^{^{^{^{^{^{^{^{}}}}}}}}}}2n^{3}+2n^{2}+n

所以这段代码的时间复杂度为O(n^3)。

二、空间复杂度

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

而我们在写代码时,完全可以用空间来换去时间。

举个例子说,要判断某年是不是闰年,你可能会花一点心思来写一个算法,每给一个年份,就可以通过这个算法计算得到是否闰年的结果。

另外一种方法是,事先建立一个有2050个元素的数组,然后把所有的年份按下标的数字对应,如果是闰年,则此数组元素的值是1,如果不是元素的值则为0。这样,所谓的判断某一年是否为闰年就变成了查找这个数组某一个元素的值的问题。

第一种方法相比起第二种来说很明显非常节省空间,但每一次查询都需要经过一系列的计算才能知道是否为闰年。第二种方法虽然需要在内存里存储2050个元素的数组,但是每次查询只需要一次索引判断即可。这种就是通过一定空间上的开销来换取一定时间上的开销

而当直接要让我们求“复杂度”时,其实通常指的是时间复杂度。

三、常见的时间复杂度

大O记法 术语 描述
O(1) 常数介 这是最好的。无论有多少数据,算法总是花费相同的时间。如:通过索引查找数组的元素。
O(logn) 对数介 很棒。这些算法在每次迭代时将数据量减半。如果您有100个项目,则需要大约7个步骤才能找到答案。有1,000个项目,需要10个步骤。1,000,000件商品只需20步。即使对于大量数据,这也非常快。如:二进制搜索。
O(n) 线性介 很好的表现。如果你有100件商品,那就可以完成100件工作。将项目数量加倍会使算法花费两倍的时间(200个工作单元)。如:顺序搜索。
O(nlogn) nlogn介 体面的表现。这比线性稍差但不太糟糕。如:最快的通用排序算法
O(n^2) 平方介 有点慢。如果你有100个项目,那么100 ^ 2 = 10,000个单位的工作。将项目数量加倍会使其慢四倍。如:使用嵌套循环的算法,插入排序。
O(n^3) 立方介 表现不佳。将输入大小加倍会使其慢八倍。如:矩阵乘法。
O(2^n) 指数介 表现很差。你应该避免使用这些算法,但有时你别无选择。仅向输入添加一位会使运行时间加倍。如:旅行售货员问题。
O(n!) 阶乘介 无比缓慢。它真的需要一百万年才能完成任何事情。

 

阅读更多
换一批

没有更多推荐了,返回首页