经常在看算法的时候,会提到算法复杂度,那算法复杂度到底是什么,是怎么样来衡量算法的?
通常衡量一个算法,是从两个维度进行考量的:
- 运行时间
- 占用内存空间
这两个都是有限资源,第一个直接影响到算法的性能,关乎用户体验,第二个则直接与硬件内存相关,直接影响成本。
所以整个算法的复杂度也是使用这两个维度作为标尺去考量一个算法。
时间复杂度
时间复杂度简单的理解就是一个算法的执行时间,由于硬件资源的不同,绝对时间没有意义。回到算法本身,每行代码都是要执行的,那执行的行数越多,所耗费的时间也越多,那么时间复杂度就越高,所以我们可以使用每行代码执行的次数来表征时间复杂度。
根据代码结构,循环次数越多,每行执行的次数就越多,所以时间复杂度可以表示为循环次数的函数
我们使用如下公式来表示时间复杂度:
Time_Complexity (n) = O (f(n))
其中,f(n)表示代码的执行次数,O代表正相关。完整名称是算法的渐进时间复杂度
O(1)
没有任何循环, 表示为O(1)
O(n)
int c = 0;
for(int a=0;a<n;a++){
c ++;
}
上面的例子中 for 循环block 执行了n次。第一行执行1次。故总共执行了(2n+1)次,当n无穷大的时候,O(2n+1) = O(n),故记为O(n)
O(n^2)
两层循环如下,复杂度为O(n^2):
int c = 0;
for(int a=0;a<n;a++){
for(int b=0;b<n;b++){
c ++;
}
}
如果将第二层的n变为m,则复杂度为O(m*n)
以此类推,三层循环就为O(n^3)
O(logn)
int a = 1
while(a < n){
a = a*2
}
假设循环m次,循环推出,那么 2^x >= n, 故 x>= logn (省略以2为底)
算法复杂度就是O(x) = O(logn)
空间复杂度
时间复杂度是用行的执行次数来衡量,而不是绝对时间,空间复杂度也是用临时占用的空间大小来衡量,时间复杂度主要是看执行次数随loop的次数的关系,而空间复杂度则是看临时使用的空间是否跟某个变量有关系。
所谓的临时占用存储空间指的就是代码中辅助变量所占用的空间,它包括为参数表中形参变量分配的存储空间和为在函数体中定义的局部变量分配的存储空间两个部分
我们使用如下公式来表示空间复杂度:
Space_Complexity (n) = O (f(n))
其中,n为问题规模的大小,f(n)表示临时占用的空间,O代表正相关。完整名称是算法的渐进空间复杂度
跟时间复杂度主要跟loop结构相关,空间复杂度主要跟动态分配的空间,以及递归、栈所需的空间相关,不涉及的都是O(1)
O(n)
程序中用到一维数组,则复杂度为O(n), n是数组的大小
int* a [] = new int [n];
for(int i=0;i<n;i++){
a[i] = i;
}
同理二维数组即为O(n^2)
复杂度的计算方法
- 用常数1取代运行时间中的所有加法常数;
- 只保留时间函数中的最高阶项;
- 如果最高阶项存在,则省去最高阶项前面的系数;