算法的时间复杂度:
参考博客:算法 二分查找的时间复杂度为O(log2N)的原因推理_阿顾同学的博客-CSDN博客
算法的时间复杂度,用来度量算法的运行时间,记作: O(f(N))。它表示随着 输入大小N的增大,算法执行需要的时间的增长速度可以用 f(N) 来描述。
上面概念可能比较抽象,下面我们用案例的方式来举例下,一般我们是先拿到f(N),然后来算下他的时间复杂度,一般我们只保留对函数增长速度较大的函数
例如:
1、f(N)=c(c是常数),我们称时间复杂度为O(1)
2、f(N)=a*N+b(a和b是常数),我们称时间复杂度为O(N)
3、f(N)=a*N^2+b*N+c(a,b,c均为常数),我们称时间复杂度为O(N^2)
4、f(N)=a*N^2*logN+b*N+c(a,b,c均为常数),我们称时间复杂度为O(N^2*logN)
常见的时间复杂度量级有:
-
常数阶O(1)
-
对数阶O(logN)
-
线性阶O(n)
-
线性对数阶O(nlogN)
-
平方阶O(n²)
-
立方阶O(n³)
-
K次方阶O(n^k)
-
指数阶(2^n)
一、对数阶:
logN的时间复杂度是除O(1)以外时间复杂度最低的算法,log2N,log3N...都可被视作logN,这是因为不同的对数函数之间只有一个常数因子的差异,而这个常数因子对于算法的增长趋势来说并不重要。举一个简单的例子来说明为什么在时间复杂度分析中底数可以被忽略。考虑两个算法,它们在不同底数下的对数时间复杂度,但它们的增长趋势相同。
算法 A 的时间复杂度为 O(log₂n),底数是2。
算法 B 的时间复杂度为 O(log₅n),底数是5。
现在,让我们比较这两个算法在不同输入规模下的运行时间。我们将分别考虑 n = 2^k 和 n = 5^k,其中 k 是一个正整数。
对于算法 A,当 n = 2^k 时,它的运行时间是 O(log₂n) = O(log₂(2^k)) = O(k)。
对于算法 B,当 n = 5^k 时,它的运行时间是 O(log₅n) = O(log₅(5^k)) = O(k)。
无论底数是2还是5,两个算法的运行时间都与 k 成线性关系,即它们的运行时间随着输入规模的增加而线性增长。这就是为什么底数在这里可以被忽略的原因。不论底数是多少,它们的增长趋势都是一样的,都是随着输入规模的增加而对数增长。
时间复杂度为O(log2N)的算法,二分查找法。
由于二分查找每次查询都是从数组中间切开查询,所以每次查询,剩余的查询数为上一次的一半,从下表可以清晰的看出查询次数与剩余元素数量对应关系。
表-查询次数及剩余数:
第几次查询 | 剩余待查询元素数量/每轮查询的查询数量变化 |
1 | N/2 |
2 | N/(2^2) |
3 | N/(2^3) |
… | … |
K | N/(2^K) |
从上表可以看出N/(2^K)肯定是大于等于1,也就是N/(2^K)>=1,我们计算时间复杂度是按照最坏的情况进行计算,也就是是查到剩余最后一个数才查到我们想要的数据,也就是
N/(2^K)>=1
=>N>=2^K
=>K<=log2N
所以二分查找的时间复杂度为O(log2N)。
由此我们可以得知,底数为2时,每次分一半查找,底数为3时每次分1/3查找。
二、指数阶:
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)。
算法的空间复杂度:
参考博客:https://www.cnblogs.com/zknublx/p/5885840.html
类似于时间复杂度的讨论,一个算法的空间复杂度(Space Complexity)S(n)定义为该算法所耗费的存储空间,它也是问题规模n的函数。渐近空间复杂度也常常简称为空间复杂度。
空间复杂度(Space Complexity)是对一个算法在运行过程中临时占用存储空间大小的量度。一个算法在计算机存储器上所占用的存储空间,包括存储算法本身所占用的存储空间,算法的输入输出数据所占用的存储空间和算法在运行过程中临时占用的存储空间这三个方面。算法的输入输出数据所占用的存储空间是由要解决的问题决定的,是通过参数表由调用函数传递而来的,它不随本算法的不同而改变。存储算法本身所占用的存储空间与算法书写的长短成正比,要压缩这方面的存储空间,就必须编写出较短的算法。算法在运行过程中临时占用的存储空间随算法的不同而异,有的算法只需要占用少量的临时工作单元,而且不随问题规模的大小而改变,我们称这种算法是“就地\"进行的,是节省存储的算法。