时间复杂度
简介:
算法的时间复杂度是一个函数,它定性描述该算法的运行时间。这是一个代表算法输入值的字符串的长度的函数。时间复杂度常用大O符号表述,不包括这个函数的低阶项和首项系数。使用这种方式时,时间复杂度可被称为是渐近的,亦即考察输入值大小趋近无穷时的情况。
分析一个算法的时间复杂度步骤:
- 找到执行次数最多的语句
- 语句执行语句的数量级
- 用O表示结果
万能方法
其次:
-
用常数1取代运行时间中的所有加法常数
-
在修改后的运行次数函数中,只保留最高阶项
-
如果最高阶项存在且不是1,那么我们就去除于这个项相乘的常数。比如3n就取n
直接看例子
循环复杂度
- 常数阶
例:段代码的大O是多少?
int sum = 0, n = 100;
printf(“I love you.com\n”);
printf(“I love you.com\n”);
printf(“I love you.com\n”);
printf(“I love you.com\n”);
printf(“I love you.com\n”);
printf(“I love you.com\n”);
sum = (1+n)*n/2;
以上代码可知都为常数加法时间复杂度为O(1)
②线性阶:一般含有非嵌套循环涉及线性阶,线性阶就是随着问题规模n的扩大,对应计算次数呈直线增长。
int i , n = 100, sum = 0;
for( i=0; i < n; i++ )
{
sum = sum + i;
}
上面这段代码,它的循环的时间复杂度为O(n),因为循环体中的代码需要执行n次。
- 平方阶
int i, j, n = 100;
for( i=0; i < n; i++ )
{
for( j=0; j < n; j++ )
{
printf(“I love FishC.com\n”);
}
}
n等于100,也就是说外层循环每执行一次,内层循环就执行100次,那总共程序想要从这两个循环出来,需要执行100*100次,也就是n的平方。所以这段代码的时间复杂度为O(n^2)。
总结:
如果有三个这样的嵌套循环就是n^3。所以总结得出,循环的时间复杂度等于循环体的复杂度乘以该循环运行的次数。
- 对数阶
int i = 1, n = 100;
while( i < n )
{
i = i * 2;
}
由于每次i*2之后,就距离n更近一步,假设有x个2相乘后大于或等于n,则会退出循环。
于是由2^x = n得到x = log(2)n,所以这个循环的时间复杂度为O(logn)。
总结:
按照我的理解循环的复杂度就是看这个循环多少次结束(不对请指出)
函数调用的时间复杂度分析
- 循环体调用
int i, j;
for(i=0; i < n; i++) {
function(i);
}
void function(int count) {
printf(“%d”, count);
}
函数体是打印这个参数,这很好理解。function函数的时间复杂度是O(1),所以整体的时间复杂度就是循环的次数O(n)。
- 假如function是下面这样:
void function(int count) {
int j;
for(j=count; j < n; j++) {
printf(“%d”, j);
}
}
事实上,这和之前平方阶的时候举的第二个例子一样:function内部的循环次数随count的增加(接近n)而减少,所以根据游戏攻略算法的时间复杂度为O(n^2)。
n++; //1
function(n); //1
for(i=0; i < n; i++) { //n
function(i);
}
for(i=0; i < n; i++) { //n^2
for(j=i; j < n; j++) {
printf(“%d”, j);
}
}
void function(int count) {
printf(“%d”, count);
}
为:1+1+n+n2,所以最后是O(n2)
最坏情况与平均情况
我们查找一个有n个随机数字数组中的某个数字,最好的情况是第一个数字就是,那么算法的时间复杂度为O(1),但也有可能这个数字就在最后一个位置,那么时间复杂度为O(n)。
平均运行时间是期望的运行时间。
最坏运行时间是一种保证。在应用中,这是一种最重要的需求,通常除非特别指定,我们提到的运行时间都是最坏情况的运行时间。
空间复杂度
简介:
对一个算法在运行过程中临时占用存储空间大小的量度
算法得存储量包括:
- 程序本身所占空间。
- 输入数据所占空间。
- 辅助变量所占空间。
输入数据所占空间只取决于问题本身,和算法无关,则只需分析除输入和程序之外得辅助变量所占额外空间。
空间复杂度是对一个算法在运行过程中临时占用得存储空间大小的量度,一般也作为问题规模n得函数,以数量级形式给出,记作:
S(n) = O(g(n))
计算规则和时间复杂度一样
举例:
无论数据规模多大,我都定义100个变量,这就叫做数据规模和临时变量数目无关。就是说空间复杂度是O(1).
int i;
for(i=0;i<n;i++)
i++;
时间复杂度是O(n),空间复杂度是O(1);
int i;
int j;
int k;
for(i=0; i<n; i++)
for(j=0; j<i; j++)
for(k=0; k<j; k++)
;
时间复杂度是O(n^3),空间复杂度还是O(1);
def fun(n):
k = 10
if n == k:
return n
else:
return fun(++n)
递归实现,调用fun函数,每次都创建1个变量k。调用n次,空间复杂度O(n*1)=O(n)。
for(i=0;i<n;++):
temp = i
变量的内存分配发生在定义的时候,因为temp的定义是循环里边,所以是n*O(1)
temp=0;
for(i=0;i<n;i++):
temp = i
temp定义在循环外边,所以是1*O(1)