时间复杂度
for(int i = 0 ; i < n ; i++) //<- 从 0 到 n,执行 n+1 次 { a++; //<- 从 0 到 n-1,执行 n 次 }
-
for 循环从 i 的值为 0 一直逐增至 n(注意,循环退出的时候 i 值为 n),因此 for 循环语句执行了 n+1 次;
-
而循环内部仅有一条语句,a++ 从 i 的值为 0 就开始执行,i 的值每增 1 该语句就执行一次,一直到 i 的值为 n-1,因此,a++ 语句一共执行了 n 次。
因此,整段代码中所有语句共执行了 (n+1)+n 次,即 2n+1 次。数据结构中,每条语句的执行次数,又被称为该语句的频度。整段代码的总执行次数,即整段代码的频度。
for(int i = 0 ; i < n ; i++) // n+1 { for(int j = 0 ; j < m ; j++) // n*(m+1) { num++; // n*m } }
-
n+1为最外层执行次数
-
n*(m+1)为内层循环总次数:外层次数 * 内循环执行次数
-
n*m为该语句执行的次数:外层实际进入循环次数*内层实际进入循环体内的次数
简化公式: (n+1)+n*(m+1)+n*m 拆分后: n+1+n*m+n+n*m 2mn+2n+1(为程序的频度)
预设n为无限大
-
最坏条件即指的是当 n、m 都为无限大时此段程序的运行时间,当 n、m 都无限大时,我们完全就可以认为 n==m
-
在此基础上,2nm+2n+1 又可以简化为 2n2+2*n+1,这就是此段程序在最坏情况下的运行时间
-
当n为无限大时,n+1常数1可以忽略不计
-
其次,对于指数级的 2n2 来说,是否在其基础上加 2n,并无关紧要;
-
甚至于,对于是否给 n2 乘 2,也可以忽略。
因此,最终频度 2n2+2n+1 可以简化为 n2 。
“使用无限大的思想”简化频度表达式
-
去掉频度表达式中,所有的加法常数式子。例如 2n2+2n+1 简化为 2n2+2n ;
-
如果表达式有多项含有无限大变量的式子,只保留一个拥有指数最高的变量的式子。例如 2n2+2n 简化为 2n2;
-
如果最高项存在系数,且不为 1,直接去掉系数。例如 2n2 系数为 2,直接简化为 n2 ;
空间复杂度
如果程序所占用的存储空间和输入值无关,则该程序的空间复杂度就为 O(1);反之,如果有关,则需要进一步判断它们之间的关系:
-
如果随着输入值 n 的增大,程序申请的临时空间成线性增长,则程序的空间复杂度用 O(n) 表示;
-
如果随着输入值 n 的增大,程序申请的临时空间成 n2 关系增长,则程序的空间复杂度用 O(n2) 表示;
-
如果随着输入值 n 的增大,程序申请的临时空间成 n3 关系增长,则程序的空间复杂度用 O(n3) 表示;