1.算法时间复杂度的定义
算法的时间复杂度,也就是算法的时间量度,记作:T(n)=O(f(n))。 它表示随问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称作算法的渐近时间 复杂度,简称为-时间复杂度。其中f(n) 是问题规模n的某个函数。
这样用O()来体现算法时间复杂度的记法,我们称之为大O记法。一般情况,随着n的增大,T(n)增长最慢的算法为最优算法。
2.算法时间复杂度例子
2.1 常数阶
public class Agr { public static void main(String args[]) { //执行一次 int m =1; //执行一次 int n =2; //执行一次 int mn = m*n; //执行一次 System.out.println(mn); }}
这个算法的运行次数是f(n)=4,依据推导方法,常数项全部变为1,那么这个算法的时间复杂度即为O(1)。事实上,这种与问题的多少(n的多少),执行恒定的算法,我们称之为O(1)的时间复杂度,简称常数阶。
2.2 线性阶
要确定某个算法的阶次,我们需要确定某个特定语句或某个语句运行的次数。因此,分析算法的时间复杂度,关键就是要分析循环结构的运行情况。
public class Agr { public static void agrn(int n) { //循环n次 for(int i=0;i
此段代码的时间复杂度即为O(n),因为循环体中的代码必须要执行n次。
2.3 对数阶
public class Agr { public static void agrn(int n) { //循环Log2 n次 int count = 1; while (count < n) { count = count * 2; System.out.print(n); } }}
由于每次count*2 ,离n更近一些,也就是有多少个2相乘后大于n,便退出循环。2x=n 得到 x=log2n。所以此循环的时间复杂度为O(logn)
2.4 平方阶
public class Agr { public static void agrn(int n) { //循环n次 for (int i = 0; i < n; i++) { //循环n次 for (int j = 0; j < n; j++) { System.out.println(n); } } }}
此为一个循环嵌套算法,内外层循环皆为n,故总循环次数为n2,所以此算法时间复杂度为O(n2).
2.5 推导出的平方阶
public class Agr { public static void agrn(int n) { //循环n+n-1+n-2+....+1 for (int i = 0; i < n; i++) { for (int j = i; j < n; j++) { System.out.println(n); } } }}
由于内层嵌套循环中j=i, 当i=0时, 循环n次,i=1时,循环n-1 ... 以此类推,总的循环次数为 n + (n-1) + (n-2) + ...... + 1 = n(n+1)/2 = n2/2 + n/2 。这时候要用到大O阶的推导方法,没有加法常数不考虑,只保留最高项, 故还剩 n2/2,另外去掉此项相乘的常数1/2,最后这个算法的时间复杂度为O(n2).
3. 推导大O阶的方法总结
1.用常数1取代运行时间中的所有加法常数,无常数的不考虑。
2.只保留最高阶项。
3.最高阶项存在且不是1,那么去掉与此项相乘的常数。
按照此3项方法,推导出来的结果,即大O阶。
4. 常见算法时间复杂度所消耗时间的大小排列
O(1) < O(logn)<O(n)<O(n2)
5. 最坏情况
当我们在查找n个随机数字数组中的某个数字,最好的情况是第一个数字就是,时间复杂度为O(1),最坏的情况遍历完整个数组才找到,时间复杂度为O(n)。 除非特别说明,我们一般指的运行时间,都是最坏情况下的运行时间,时间复杂度也是最坏情况下的时间复杂度。