时间复杂度
1.代码的执行次数——T(n)
一个代码的执行次数会用T(n)表示,n是输入数据的大小或者是输入数据的数量。而T是在输入数量为n的时候,这一段代码的总执行次数。
当我们的代码量到了一定的数量级后,此时T(n)就会较难得到准确值,所以算法一般使用T(n)的估算值来衡量算法的复杂度,而这个估算值便是时间复杂度,用O(n)表示。
2.如何由T(n)得到时间复杂度
- 若T(n)等于一个常数的话:
时间复杂度可以直接估算为O(1)。
- 若T(n)=(常数)×n+(常数)的话:
我们可以直接去掉加号后面的常数,因为随着n的增大,(常数)×n项也会越来越大,而后半部分的(常数)不变,可以直接忽略。而第一部分的常数我们可以直接估算为1,或者直接去掉它,因此它的最终复杂度为O(n)。
- 对于多项式:
我们只需要保留n的最高次项。
【总结】
T(n)若是常数,则时间复杂度为O(1);反之时间复杂度为O(去掉系数的n的最高次项)。
3.一些“奇怪”的例子
①第一个例子
void function()
{
for (int i=0;i<n;++i)
{
for(int j=i;j<n;++j)
{
printf("山风在和第%d周目的%d号选手打招呼!",i,j);
}
}
}
分析过程如下:
T
(
n
)
=
n
+
(
n
−
1
)
+
(
n
−
2
)
+
…
…
+
2
+
1
=
n
×
(
n
+
1
)
2
=
1
2
n
2
+
1
2
n
=
O
(
n
2
)
T(n)=n+(n-1)+(n-2)+……+2+1=\frac{n×(n+1)}{2}=\frac{1}{2}n^2+\frac{1}{2}n=O(n^2)
T(n)=n+(n−1)+(n−2)+……+2+1=2n×(n+1)=21n2+21n=O(n2)
②第二个例子
void function(int n)
{
for (int i=1;i<n;i*=2)
{
printf("山风不打咩!");
}
}
T(8)=3 T(16)=4 可以得到
2
T
(
n
)
=
n
2^{T(n)}=n
2T(n)=n
但是这样是不能表示时间复杂度的,所以我们把T(n)提取出来得到
T
(
n
)
=
3
×
l
o
g
2
n
T(n)=3×log_2^n
T(n)=3×log2n
4.时间复杂度对比
从左到右时间复杂度依次增大,越往后面增幅越明显:
常
数
时
间
:
O
(
1
)
→
对
数
时
间
:
O
(
l
o
g
n
)
→
线
性
时
间
O
(
n
)
→
线
性
对
数
时
间
O
(
n
l
o
g
n
)
→
二
次
时
间
O
(
n
2
)
→
指
数
时
间
O
(
2
n
)
常数时间:O(1)→对数时间:O(logn)→线性时间O(n)→线性对数时间O(nlogn)→二次时间O(n^2)→指数时间O(2^n)
常数时间:O(1)→对数时间:O(logn)→线性时间O(n)→线性对数时间O(nlogn)→二次时间O(n2)→指数时间O(2n)
5.一道题
Q:设某算法的计算时间表示为递推关系式T(n)=T(n-1)+n(n为正整数)及T(0)=1,该算法的时间复杂度是多少?
A:我们可以将T(n-1)中的n-1作为参数,再代入到题目的式子中,就会得到T(n-2)+(n-1)+n,之后我们就可以将n-2作为参数,再代入到式子中,以此类推直到T(0)出现,而T(0)=1,于是我们得到T(0)=1+n×(n+1)÷2=1。所以最后得到时间复杂度O(n^2)。