目录
1.复杂度的概念
2.复杂度的重要性
3.时间复杂度
3.1⼤O的渐进表⽰法
4.空间复杂度
5.提高算法效率的方法
算法效率是指算法执行的时间,具体来说,是通过依据该算法编制的程序在计算机上运行时所消耗的时间来度量的。算法效率是衡量算法优劣的重要指标之一,主要包括时间效率和空间效率两个方面。
1.复杂度的概念
算法在编写成可执⾏程序后,运⾏时需要耗费时间资源和空间(内存)资源 。因此衡量⼀个算法的好坏,⼀般是从时间和空间两个维度来衡量的,即时间复杂度和空间复杂度。
时间复杂度主要衡量⼀个算法的运⾏快慢,⽽空间复杂度主要衡量⼀个算法运⾏所需要的额外空间。在计算机发展的早期,计算机的存储容量很⼩。所以对空间复杂度很是在乎。但是经过计算机⾏业的迅速发展,计算机的存储容量已经达到了很⾼的程度。所以我们如今已经不需要再特别关注⼀个算法的空间复杂度。
2.复杂度的重要性
复杂度的重要性主要体现在以下几个方面:
评估算法效率:复杂度是衡量算法执行过程中所需资源(如时间和空间)的数量,通常与输入数据的大小有关。通过分析算法的复杂度,可以评估算法的效率,从而选择最优的解决方案1。
优化程序性能:在软件开发中,算法复杂度直接影响程序的运行效果和用户体验。通过优化算法复杂度,可以减少程序运行时间,降低资源消耗,提升程序的整体性能2。
指导算法设计:在设计算法时,了解复杂度的概念可以帮助开发者设计出更高效的算法。例如,通过分析时间复杂度和空间复杂度,可以选择使用更优的数据结构和算法,避免使用效率低下的方法3。
帮助理解算法特性:复杂度不仅包括时间复杂度和空间复杂度,还包括其他资源如并行计算中的处理器数量等。理解这些复杂度的分类和计算方法,有助于全面评估算法的性能和资源消耗3。
促进算法改进:通过分析算法的复杂度,可以发现算法中的瓶颈和低效部分,进而进行优化和改进。例如,通过减少循环次数、优化数据结构等方法,可以显著降低算法的时间复杂度和空间复杂度4。
综上所述:复杂度在评估算法效率、优化程序性能、指导算法设计、理解算法特性和促进算法改进等方面都具有重要作用。
3.时间复杂度
时间复杂度也称为时间效率,主要衡量一个算法的运行速度,在计算机科学中,算法的时间复杂度是⼀个函数式T(N),它定量描述了该算法的运⾏时间。
以下面的代码为例:
void Func1(int N)
{
int count = 0;
for (int i = 0; i < N ; ++ i)
{
for (int j = 0; j < N ; ++ j)
{
++count;
}
} f
or (int k = 0; k < 2 * N ; ++ k)
{
++count;
} i
nt M = 10;
while (M--)
{
++count;
}
}
代码中执行的基本操作次数即++count语句执行的次数就是我们需要求的时间复杂度,下面我们来对代码进行分析:
T (N) = N^2 + 2 ∗ N + 10
• N = 10 T(N) = 130
• N = 100 T(N) = 10210
• N = 1000 T(N) = 1002010
通过对N取值分析,对结果影响最⼤的⼀项是 N^2
实际中我们计算时间复杂度时,计算的也不是程序的精确的执⾏次数,精确执⾏次数计算起来还是很⿇烦的(不同的⼀句程序代码,编译出的指令条数都是不⼀样的),计算出精确的执⾏次数意义也不⼤,因为我们计算时间复杂度只是想⽐较算法程序的增⻓量级,也就是当N不断变⼤时T(N)的差别,上⾯我们已经看到了当N不断变⼤时常数和低阶项对结果的影响很⼩,所以我们只需要计算程序能代表增⻓量级的⼤概执⾏次数,复杂度的表⽰通常使⽤⼤O的渐进表⽰法。
3.1⼤O的渐进表⽰法
时间复杂度是通过分析算法中基本操作重复执行的次数来计算的,通常用大O符号(O)表示。例如,对于简单的线性搜索算法,其时间复杂度为O(n),表示在最坏情况下需要遍历n个元素。
推导⼤O阶规则
1. 时间复杂度函数式T(N)中,只保留最⾼阶项,去掉那些低阶项,因为当N不断变⼤时,
低阶项对结果影响越来越⼩,当N⽆穷⼤时,就可以忽略不计了。
2. 如果最⾼阶项存在且不是1,则去除这个项⽬的常数系数,因为当N不断变⼤,这个系数
对结果影响越来越⼩,当N⽆穷⼤时,就可以忽略不计了。
3. T(N)中如果没有N相关的项⽬,只有常数项,⽤常数1取代所有加法常数。
根据规则我们可以知道上面的代码Func1()的时间复杂度为:O(N^2)。
4.空间复杂度
空间复杂度也称为空间效率,主要衡量一个算法所需要的额外空间。空间复杂度考虑的是算法在运行过程中临时占用存储空间的规模,包括辅助空间和输入输出数据所占用的空间。
空间复杂度计算规则基本跟实践复杂度类似,也使⽤⼤O渐进表⽰法。
以以下递归代码为例:
long long Fac(size_t N)
{
if(N == 0)
return 1;
return Fac(N-1)*N;
}
Fac()递归调⽤了N次,额外开辟了N个函数栈帧,每个栈帧使⽤了常数个空间
因此空间复杂度为: O(N)
注意:函数运⾏时所需要的栈空间(存储参数、局部变量、⼀些寄存器信息等)在编译期间已经确定好了,因此空间复杂度主要通过函数在运⾏时候显式申请的额外空间来确定
5.提高算法效率的方法
- 选择合理的存储结构:选择合适的存储结构可以减少访问和操作数据的时间和空间开销。
- 使用直接初始化:避免在循环中多次初始化变量,减少不必要的计算。
- 尽量减少值传递,多用引用来传递参数:这样可以避免复制大量数据。
- 减少除法运算的使用:除法运算通常比乘法、加法和减法更耗时。
- 避免使用多重继承:多重继承会增加类的复杂度和运行时的开销。
- 将小粒度函数声明为内联函数:这样可以减少函数调用的开销1。
通过这些方法,可以有效提高算法的执行效率和空间利用率,从而优化程序的性能。