目录
前言
因为我们知道,对于一个程序的效率高低,不仅仅看起来简单就是高效,最主要的我们要通过时间复杂度以及空间复杂度去判别其效率高低。
而对于时间复杂度,一般衡量的是该程序执行时间的长短,而空间复杂度则表示的该程序运行所需要的额外空间的大小。
好的,那么我们了解了关于算法复杂度计算的两个标准了之后,我们进入正文。
-------------------------------------------正文如下---------------------------------------------------
一,时间复杂度
1.1基本定义
标准定义:算法的时间复杂度是一个函数(式),它定量的描述了一个算法的执行时间。
那么我们知道,对于一个算法来说,如果想求出其运行所需的确定时间,其实是不现实的,因为我们对于每个程序都放在机器上去运行一遍,这样是很繁琐且没必要的。所以一般情况下,算法中基本操作的执行次数,我们将其认定为算法的时间复杂度。
1.2求值方法
因为时间复杂度一般认为是一个函数式,所以对于每个算法,在计算时间复杂度时,我们会求出一个函数式,然后将其化简。
而同时我们知道,如果一个式子中同时存在指数,加法,乘法等,我们认为因为加减或者乘除一个数对于整个数来说,改变的是很小的,因为指数的增加很大,所以这里我们对于该函数式有一个默认的化简方法,即大O的渐进表示法。
1.3大O渐进表示法
大O符号:数学中用于表示渐进行为的数学符号
那么对于大O阶的求法有如下规定:
1.用常数 1 替代式子中所有加法常数。
2.在修改后的式子中,只保留最高阶项。
3.如果最高阶存在且不是常数,那么将与该最高阶数的乘法去除,得到的便是大O阶。
所以,我们知道了,其实对于复杂度的求解并不是细化到 1 的,而是将一些对最终结果影响不大的数去除,最后用一个大概的数来表示。
1.4复杂度的三种情况
那么我们知道,比如现在我们打算求一个二分查找的时间复杂度。
最好的情况:首先,最好的情况,我们要找的那个数就是现在第一次取到的数,当然这里时间复杂度便为 O(1);
最差的情况:其次,如果我们需要找的数不在这个有序数组中,那么时间复杂度将为以2为底,N(表示数组元素个数)的对数;
中间的状态:最后,当然还有处于中间的状态,那么该复杂度为前两者的一半。
那么,其实对于这三种情况来说,我们一般会认为最差的情况是该算法的时间复杂度。因为我们不确定最后会得出那种结果,为了保险起见,一般最坏的那种就是时间复杂度。
1.5案例解析
案例一
好的,了解了以上基本内容之后,我们通过几个例子来具体认识一下,时间复杂度。
那么我们看到,该函数有两个循环,首先我们得到的函数式:O(n)=M+N;这里因为我们不知道M和N那个的值到底哪一个数远大于另一个数,所以这该程序的时间复杂度就是O(n)=M+N。
而一旦我们知道M远大于N之后,则该复杂度就变为了 O(M) ,反之变为 O(N)了。如果两个值是相等的,任意写一个即可(理由:大O阶表示法规定第三条)。
案例二
案例二我们通过冒泡排序来分析时间复杂度的计算:在计算之前,其实对于计算时间复杂度这条默认的规定是很重要的:
计算时间复杂度,一般不会根据其循环次数来决定,而是要分析该程序真正执行的过程。
根据上面默认规定,我们通过冒泡排序的执行过程来分析:
首先,我们知道,冒泡排序就是从一组数从首元素开始,两两比较,然后一直到这组数结束,将这组数中最大的那个数放在整个数的末尾,这是第一轮结束;
然后第二轮,此时对于要遍历的数组会少一个元素,因为最后那个数已经是最大的了,没有必要再比较一次了。然后接下来就跟第二轮是一样的了,直到最后需要遍历的数只剩一个。
那么好像该算法的时间复杂度为 :
B(N)=(n-1)+(n-2)+(n-3)+....+1,
那么最后求出结果化简可得 O(N^2)。
案例三
那么案例三,我们来计算一个二分查找的时间复杂度:
这里同样,我们根据二分查找的过程来分析其时间复杂度。
首先,对于二分查找,每次我们会设置一个一组数中的中间数,然后通过比较该数与要查找的数,如果两者不相等,则需要根据的两数大小,舍弃中间数左边或者右边的所有数,然后接下来再根据实际情况可能进行对半减数。
案例四
接下来我们通过斐波那契数列的递归算法来分析时间复杂度的算法:
对于递归算法,我们默认:
单次递归算法的复杂度:每次递归调用的次数(即单次函数调用的次数)* 递归的次数
这里我们假设 x 为最后缺的一部分递归调用,如下图所示:
所以可得,
Fib(N) = 2^0 + 2^1 + 2^2 + 2^3 + ... +2^(N-1) - x
Fib(N) = 2^N - 1 - x
Fib(N) = O(2^N)
好的,那么看到这里,你对与时间复杂度的计算一定有了一个自己的想法了吧。那么接下来我们来了解一下有关空间复杂度的内容。
二,空间复杂度
空间复杂度也是一个函数式,不过其表示一个算法在运行过程中临时占用的存储空间大小。
而这里空间复杂度计算的也不是占用了几字节的空间,而是变量的个数。
注:对于空间复杂度的计算,与以上时间复杂度的内容形式基本相同,都是用大O阶表示法来表示,但是不同的是计算的方式是不同的,空间复杂度计算的是变量的个数。
那么同样的,我们通过上面的案例四,斐波那契数列的递归实现来计算空间复杂度:
我们还是通过这个图来计算:
首先,因为函数调用得时候,产生的堆栈是可以重复利用的,这也就是空间是可重复利用的,而时间是一去不复返的。
所以,这里我们就不需要多次创建相同的堆栈了。所以此时我们只需要计算不同的变量个数为N,所以空间复杂度就为 O(N):
Fib(N) = O(N)
好的,那么对于算法复杂度就结束啦!如有错误,还请指正呀!