(1)时间复杂度:
看下面这个例子
for(i = 0; i < n; ++i)1
for(j = 1; j < n; j++)2
{c[i][j]=0;} 3
语句1执行次数: 1+n+n=2n+1;
语句2执行次数: n* (1+n+n)=n*(2n+1)=2n^2+n;
语句3执行次数: 双重循环 n^2;
总共f(n)=2n+1+2n^2+n+n^2=3*n^2+3n+1--->O(n^2)
电脑的计算速度很快,一秒钟都上亿次,所以低阶项,和系数不考虑。
时间复杂度要遵循:
1、只保留高阶项,低阶项直接丢弃
2、系数不要
练习1:{++x;s = 0;} O( 1 )
3、执行次数是常数是为O(1)
练习2:
for(i = 2; i< n; ++i)
for(j = 2; j < i-1;++j)
{++x; a[i][j]=x;}
虽然最核心的语句有两句,但是时间复杂度的计算系数不要,所以时间复杂度O( n^2 )
练习3:
for(int i = 0;i < n;i++);
i的变化为:1 2 3 4 ... n
所以时间复杂度O( n )
练习4:
for(int i = 0;i < n; i *= 2)
i 的变化为:1 2 4 8 ...n
2^x=n--->x = log以2为底的n次方(这里没法打出来)时间复杂度O( log以2为底的n次方 )
练习5:
int Age(int n)
{
if(n==1)
{
return 10;
}
return Age(n-1) + 2;
}
这是递归问题:例如求n = 5 ,要用Age(5)-->Age(4)-->Age(3)-->Age(2)-->Age(1),然后在返回Age(5)<--Age(4)<--Age(3)<--Age(2)<--Age(1),要算两遍,是2倍的关系,但是时间复杂度的计算系数不要,所以时间复杂度O(n)
(2)空间复杂度:实现算法需要的额外辅助空间和问题之间的关系
练习1:{++x;s = 0;}
空间复杂度:O( 1 )
练习2:
for(i = 2; i< n; ++i)
for(j = 2; j < i-1;++j)
{++x; a[i][j]=x;}
空间复杂度:O( 1 )
练习3:
for(int i = 0;i < n;i++);
空间复杂度:O( 1 )
练习4:
for(int i = 0;i < n; i *= 2)
空间复杂度:O( 1 )
练习5:
int Age(int n)
{
if(n==1)
{
return 10;
}
return Age(n-1) + 2;
}
空间复杂度:O( n ),递归调用时并不会释放空间,而是返回时逐渐释放。返回斐波那契数列有循环和递归的两种写法,下面我们利用时间复杂度和空间复杂度来解释为什么递归的写法不并不太好。
int Fabio1(int n)//循环,
{int f1 = 1;
int f2 = 1;
int f3 = 1;
for(int i=2;i<n;i++)
{
f3 = f1 + f2;
f1 = f2;
f2 = f3;
}
return f3;
}
时间复杂度O(n),空间复杂度O(1)
int Fabio(int n)//递归
{
if(n==1 || n==2)
{
return 1;
}
return Fabio(n-1) + Fabio(n-2);
}
时间复杂度O(2^n ),空间复杂度O(n),相较于循环的写法递归的空间复杂度较大,因为栈一般的大小为1M,当n较大时,容易出现栈溢出,所以用递归的写法并不是特别好。