一.引言
正所谓"条条大路通罗马",要通过编写程序来实现某种目的,毫无疑问有着各种各样的方法,算法(Algorithm)便是描述解题所采用的方法。但是,在我们运行程序的时候,不同的算法的效率一般有优劣之分。那么如何衡量程序实现的效率呢?这里我们引入复杂度的概念。
二.算法复杂度
时间复杂度:主要衡量一个算法的运行快慢空间复杂度:主要衡量一个算法运行所需要的额外空间。
三.时间复杂度
int i=0;
for(i=0;i<n;i++)
{
printf("%d ",i);
}
如上述的简单代码,若给定数据n,则循环体内的基础语句printf会执行F(n)=n次,此时它的时间复杂度为O(N)。
那么为什么用O(N)表示呢?这里就需要介绍一下时间复杂度的表示方法
四.时间复杂度表示方法-大O的渐进表示法
推导大 O 阶方法:1 、用常数 1 取代运行时间中的所有加法常数。2 、在修改后的运行次数函数中,只保留最高阶项。3 、如果最高阶项存在且不是 1 ,则去除与这个项目相乘的常数。得到的结果就是大 O 阶
因此,按照上述规则,若基础语句需要执行F(n)=4*n^2+n+1次,则由于其最高阶项为4*n^2,按照规则,保留最高阶项,我们去除其余项n+1,然后去除其系数4,得到大O表示法的复杂度为O(n^2)
五.时间复杂度的计算及案例
1.
// 计算Func2的时间复杂度
void Func2(int N) {
int count = 0;
for (int k = 0; k < 2 * N ; ++ k)
{
++count;
}
int M = 10;
while (M--)
{
++count;
}
printf("%d\n", count);
}
分析代码易得:F(n)=2*n+10,因此时间复杂度为O(N)。
2.
// 计算Func3的时间复杂度?
void Func3(int N, int M) {
int count = 0;
for (int k = 0; k < M; ++ k)
{
++count;
}
for (int k = 0; k < N ; ++ k)
{
++count;
}
printf("%d\n", count);
对于两个未知数M和N,执行次数为M+N。 若M远远大于N,时间复杂度可写为O(M),反之若N远大于M,时间复杂度可写为O(N),若两者相近,则O(M),O(N)均可(可视为M*2或N*2)。但实际上由于M和N的大小关系不确定,因此时间复杂度用O(M+N)来表示。
3.
// 计算Func4的时间复杂度?
void Func4(int N) {
int count = 0;
for (int k = 0; k < 100; ++ k)
{
++count;
}
printf("%d\n", count);
}
执行次数F(n)为常数100,按照规则常数用1替代,表示其规模的时间复杂度为O(1)。
4.
// 计算BinarySearch的时间复杂度?
int BinarySearch(int* a, int n, int x) {
assert(a);
int begin = 0;
int end = n-1;
while (begin < end)
{
int mid = begin + ((end-begin)>>1);
if (a[mid] < x)
begin = mid+1;
else if (a[mid] > x)
end = mid;
else
return mid;
}
return -1; }
经典二分查找(折半查找)算法,对于给定的n个数据,其每次会操作将查找范围缩减至约一半,最好的情况下查找1次,最坏情况查找x次后范围缩减至1个数据,对其判断后查找结束。由数学知识,得
,时间复杂度为最坏情况,可表示为O(logn)。
那么时间复杂度就介绍至此。