一、首先了解什么是算法的时间复杂度
1.算法的时间复杂度定义
官方话:在计算机科学中,时间复杂性,又称时间复杂度,算法的时间复杂度是一个函数,它定性描述该算法的运行时间。这是一个代表算法输入值的字符串的长度的函数。时间复杂度常用大O符号表述,不包括这个函数的低阶项和首项系数。使用这种方式时,时间复杂度可被称为是渐近的,亦即考察输入值大小趋近无穷时的情况。
人话:就是计算一个算法的基本操作总次数。(也就是构造一个关于问题规模与基本操作次数之间的关系的函数)
1.将算法中基本操作的执行次数作为算法时间复杂度的度量 算法时间复杂度不是执行完一段程序的总时间,而是基本操作的总次数。
2.明确算法中的基本操作,计算出基本操作重复执行的次数。
3.找到一个n,可以称为问题的规模。
4.基本操作的次数是n的一个函数f(n)
2.必须知道的时间复杂度知识
T(n)的意思如下:
①T表示某段代码的总执行次数,也就是基本操作总数
②n就是数据运算的大小范围,也就是问题规模
一个重要的定理:
若 是一个m次多项式,则T(n) = O(n^m)。
定理说明了在计算算法的时间复杂度时,可以忽略所有低次幂项和最高次幂的系数,这样就可以简化算法分析,也体现出增长率的含义。
人话来说就是:
(1)T(2)、T(3)、T(k) k是常数;那么O(k)无论什么时候都为 1。
(2)若T(n) = 222n^3 + 2222n^2,那么就看最高次幂就行也就是T(n) = O(n^3)
也就是判断T(n)是否为常数
是:T(n) = 1
不是:T(n)的时间复杂度为:O(保留最高次幂的项,同时去除最高次幂的系数)
3.算法的时间复杂度的区分
二、时间复杂度的计算方式
1.计算时间复杂度思路
通过以上分析,总结出计算一个算法时间复杂度的具体步骤如下:
(1)确定算法中的基本操作以及问题的规模。
(2)根据基本操作执行情况计算出规模n的函数f(n),并确定时间复杂度为T(n)=O(f(n)中增长最快的项/此项的系数)。
注意:有的算法中基本操作的执行次数不仅跟初始输入的数据规模有关,还和数据本身有关。例如,一些排序算法,同样有n个待处理数据,但数据初始有序性不同,则基本操作的执行次数也不同。一般依照使得基本操作执行次数最多的输入来计算时间复杂度,即将最坏的情况作为算法时间复杂度的度量。
2.如果大家觉得上面有点难理解,我给出一个简易版的做题思路
时间复杂度做题步骤:
(1)知基本操作是什么(最内层的循环语句作为基本操作)
选循环语句中那条语句作为基本操作,主要看与问题规模n
的关系
(2)看问题规模(如果有多层循环,看最外层循环)
(3)接下来分步写出操作一次、两次、三次知道m
次所带来的值的变化情况
(4)总结规律,列出m=多少n的表达式,其中的m就是f(n),
也就是时间复杂度(5)写出f(n) = n,从而计算出O(n)
三、例题
1.例题1:时间复杂度为O(n)
解题思路:
(1)确定基本操作次数:i+=2;为什么选i+=2;而不选++j呢,因为i与问题规模有关,j与问题规模无关
(2)确定问题规模:n;
(3)计算前几个值,知晓它的规律:
① i = 1+2;j++ ② i = 1 + 2 + 2 ③ i = 1 + 2 + 2 + 2 …… (假设第m次就i就不满足小于n了)那么就有:第m次运算:i = 1 + 2m;
(4) 总结规律,列出m与n的关系,从而转化为f(n)与n的关系:(1 + 2m) - k = n(此k的作用是调整(1 + 2m)去逼近与n,这里可以采用下数学的极限思想!)
(5)得m与n的关系,也就是m = f(n) = ,那么T(n) = O(n),时间复杂度就是O(n)
敲黑板!!!
如果有朋友看不懂上面的意思,那么我就再写个详细,如下:
第一步:找出基本操作,确定规模n。
(1)找基本操作。基本操作即以求时间复杂度为目的的前提下,重复执行次数和算法的执行时间成正比的操作。通俗地说,这种操作组成了算法,当它们都执行完的时候算法也结束了,多数情况下取最深层循环内的语句所描述的操作作为基本操作,显然题目中++j;与i+=2;这两行都可以作为基本操作。
(2)确定规模。由循环条件i<n可知,循环执行的次数(基本操作执行的次数)和参数n有关,因此参数n就是我们所说的规模no
第二步:计算出n的函数 f(n)。
显然,n确定以后,循环的结束与否和i有关。i的初值为1,每次自增2,假设i自增m次后循环
结束,则i最后的值为1+2m,因此有1+2m+K=n(其中K为一个常数,因为在循环结束时i的值稍大于 n,为了方便表述和进一步计算,用K将1+2m修正成n,因为K为常数,所以这样做不会影响最终时间复杂度的计算),解得m=(n-1-K)/2,即f(n)=(n-1-K)/2,可以发现其中增长最快的项为n/2,因此时间复杂度T(n)=O(n)。
2.例题2:时间复杂度为O(n^2)
解题思路:
(1)确定基本操作数(看最内层循环的基本操作次数,也就是++x)
(2)确定问题规模:看最外层的for循环(为什么不看最里层的for循环呢,因为没必要哇!如果你连第一个循环都进不来,谈何第二层循环呢?还有就是看以最外层循环为基准去看问题,也还是一样要一层层进去数,所以就选择最外层循环为问题规模!)
(3)计算前几个值,知晓它的规律(外层循环的次数以①,②……表示)(内层循环的次数以1,2……表示),则:
① 1. i = 0 , j = 1 , ++x ; 2. i = 0 , j = 2 , ++x ; 3. i = 0 , j = 3 , ++x …………
第n - 1次:i = 0 , j = n - 1 , ++x(为什么没有n次呢,因为j < n,所以没有第n次)同理如下:
② 1. i = 1 , j = 2 , ++x ; 2. i = 1 , j = 3 , ++x ; 3. i = 1 , j = 4 , ++x …………
第n - 2次:i = 0 , j = n - 1 , ++x
(4)总结规律,列出m与n的关系,从而转化为f(n)与n的关系:
从规律中得知n、次数与i的关系的关系有:次数 = n - (i + 1)
i = 0 -> n - 1次
i = 1 -> n - 2次
i = 2 -> n - 3次
…………
i = n - 2 -> n - (i + 1) = 1
i = n - 1 -> n - (i + 1) = 0
由等差数列求和公式得:
总执行基本操作次数为:
(5)所以T(n) = O(n^2)
3.例题3:时间复杂度为O(n的平方根)
解题思路:
(1)确定基本操作:s = s + i
(2)确定问题规模:n
(3)计算前几个值,知晓它的规律:
① i = 0 , s = 0 + 1 ; ② i = 1 , s = 0 + 1 + 2 ; ③ i = 2 , s = 0 + 1 + 2 + 3…………
假设到第m次,s就不满足小于n:s = 1 + 2 + 3 + …… + m
(4)总结规律,列出m与n的关系,从而转化为f(n)与n的关系:
由等差数列求和公式得:
那么s就是无限趋近于n,就有了
(5)T(n) = O()
注意:其中的m怎么解呢,可以用求根公式求解
m^2 + m - 2k = 2n
x1,x2 =
结果就显而易见了!!!
重点!!!
说白了就是在找m次基础操作使得某个值x无限接近于问题规模n,从而利用 (m次操作次数后的x - k = n)
4.例题4:时间复杂度O(logn)
解题思路:
(1)确定基本操作:i = i * 2
(2)确定问题规模:n
(3)计算前几个值,知晓它的规律:
① i = 1 * 2 ; ② i = 1 * 2 * 2 …………同理可得 假如第m次就停止,那就是 i = 1 * 2^m
(4)总结规律,列出m与n的关系,从而转化为f(n)与n的关系:
1 * 2^m - k = n;
2^m = n - 1 + k;
m = f(n) = ;
(5)O(n) = logn;(注意:底数也要去掉,就留下n)
5.例题5:时间复杂度O(nlogn)
解题思路:
(1)确定基本操作:x = x * 2
(2)确定问题规模:最外层的n
直接给简便的理解,因为最外层是执行了n次,里面执行了n - 1次,由例题4知,时间复杂度
T(n) = O(nlogn)