算法执行时间随输入规模(N)增长的渐进趋势的数学函数,具体表现为算法中基本操作的执行次数。
由于一个算法所花费的时间与其中语句的执行次数成正比例,所以算法中的基本操作的执行次数,为算法的时间复杂度。
为什么不用时间呢?
即:
找到某条基本语句与问题规模N之间的数学表达式,就是算出了该算法的时间复杂度
// 请计算一下Func1中++count语句总共执行了多少次?
void Func1(int N)
{
int count = 0;
for (int i = 0; i < N ; ++ i)
{
for (int j = 0; j < N ; ++ j)
{
++count;
}
}
for (int k = 0; k < 2 * N ; ++ k)
{
++count;
}
int M = 10;
while (M--)
{
++count;
}
printf("%d\n", count);
}
Func1执行的基本操作次数:
那么,我们每次表示时间复杂度都要写像这样长长的表达式吗?
麻烦,而且我们没有必要去精确计算执行次数,只需要一个大概次数,所以我们使用大O渐进表示法。
大O符号(Big O notation):是用于描述函数渐进行为的数学符号。 推导大O阶方法:
目标:忽略低阶项和常数系数,聚焦最高阶项的增长趋势。
推导步骤:
F(N)=1000
→ O(1)
)。
F(N)=N³ + N² + 1
→ O(N³)
)。
F(N)=3N²
→ O(N²)
)。
使用大O的渐进表示法后,Func1的时间复杂度为:
大O的渐进表示法去掉了那些对结果影响不大的项,简洁明了的表示出了执行次数。
此外,有一些算法的时间复杂的存在最好、最坏和平均的情况:
看一个例子:在一个长度为N数组中搜索一个数据x
一般时间复杂度取用算法的最坏运行情况
所以:数组中搜索数据的时间复杂度为O(N)
for (int i = 0; i < N; i++) { // O(N)
for (int j = 0; j < 100; j++) { // 固定执行100次
// 操作
}
}
总时间复杂度为 O(N)
,而非 O(N²)
他的时间复杂度依然为:
同样的:
他的时间复杂度依然为:
空间复杂度也是一个数学表达式(函数),是对一个算法在运行过程中临时占用存储空间大小的量度(注意这个临时) 。也使用大O渐进表示法。
注意:函数运行时所需要的栈空间(存储参数、局部变量、一些寄存器信息等)在编译期间已经确定好了,因此空间复杂度主要通过函数在运行时候显式申请的额外空间来确定。
你知道为什么要有这个”临时“吗?
因为空间是可以重复利用的,算法中开辟过的空间重复使用空间复杂度不会增加。 而时间是一去不复返的,无法重复使用。
看一个例题你就明白了
// 计算Fib的空间复杂度?
// 返回斐波那契数列的前n项
long long Fib(size_t N)
{
if(N < 3)
return 1;
return Fib(N-1) + Fib(N-2);
}
这里的时间复杂度不难推导:O(2^N)
那么空间复杂度呢?
也是O(2^N)
吗?
没错,这里重复利用了空间,实际上空间复杂度为:
O(N)
(递归栈深度),而迭代法为 O(1)
。扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有