一. 定义:

在进行算法分析时,语句总的执行次数T(n) 是关于问题规模n的函数,
进而分析T(n) 随 n 的变化情况并确认T(n) 的数量级。
算法的时间复杂度,也是算法的时间度量,记作:T(n) = O(f(n)).
它表示随问题规模的增大,算法执行时间的增长率和f(n) 的增长率相同
称作算法的渐近时间复杂度,简称时间复杂度. 其中f(n)是问题规模n 的
的某个函数

二. 推导大O阶方法
  1. 用常数1 取代运行时间中的所有加法常数
  2. 在修改后的运行次数函数中, 只保留最高阶项
  3. 如果最高阶项相乘一个常数且不是1, 则去掉这个常数

1. 常数阶时间复杂度 : O(1)
  1. 以下程序片段的时间复杂度函数 :f(n) = 1+1+1 = 3
  2. 根据推导大O阶方法第一条: 用1 代替常数项
  3. 所以,时间复杂度为O(f(n)) = O(1); 称为常数阶
  1. int sum = 0, n= 100; //执行一次
  2. int sum = 0, n= 100; //执行一次
  3. int sum = 0, n= 100; //执行一次

2. 线性阶时间复杂度: O(n)
  1. 以下程序片段的时间复杂度函数 :f(n) = n
  2. 根据推导大O阶方法第二条: 只保留最高阶项
  3. 所以,时间复杂度为O(f(n)) = O(n); 称为线性阶
  1. for (int i = 0; i < n ; i++) {
  2. System.out.println("i = "+i); // 执行n次
  3. }

3. 对数阶时间复杂度 :O(logn)
  1. 以下程序片段的时间复杂度函数 :f(n) = log(2)n
  2. 所以,时间复杂度为O(f(n)) = O(logn); 称为对数阶
  1. int count = 1;
  2. while(count < n ){
  3. // 每执行一次,count 乘 2
  4. // 设x次后, count 大于 n ; 终止程序
  5. // 所以函数; 2^x = n --> x = log(2)n
  6. count = count*2; // 这里执行 log(2)n 次
  7. }

4. 平方阶时间复杂度:O(n^2)

example 1:

  1. 以下程序片段为双重循环,所以执行次数为每个循环次数的乘积;时间复杂度函数 :f(n) = n^2
  2. 根据推导大O阶方法第二条: 只保留最高阶项
  3. 所以,时间复杂度为O(f(n)) = O(n^2),称为平方阶
  1. for (int i = 0; i < n; i++) {
  2. for (int j = 0; j < n ; j++) {
  3. System.out.println("i = "+i+" j="+j); //执行n*n次
  4. }
  5. }

example 2:

  1. 以下程序片段时间复杂度函数 :f(n) = n^2/2+n/2
  2. 根据推导大O阶方法第二条: 只保留最高阶项 :f(n) = n^2/2
  3. 根据推导大O阶方法第三条: 如果最高阶项相乘一个常数且不是1, 则去掉这个常数:f(n) = n^2
  4. 所以, 时间复杂度为O(f(n)) = O(n^2),称为平方阶
  1. for (int i = 0; i < n; i++) {
  2. for (int j = i; j < n ; j++) {
  3. // 注意; 内层的j = i,
  4. //所以,每次i 增加 1, 内层循环就减少一次
  5. // 则,
  6. // 当i=0; 时,内层循环执行 n次
  7. // 当i=1时, 内层循环执行 n-1 次
  8. //....
  9. //当i=n-1, 内层循环执行 1 次
  10. // 所以,总执行次数相加为: n+(n-1)+(n-2)+...+1 = n(n+1)/2 【高斯求和】
  11. System.out.println("i = "+i+" j="+j);
  12. }
  13. }

三、常见的时间复杂度
执行次数函数 非正式术语
12 O(1) 常数阶
2n+3 O(n) 线性阶
3n^2+2n+1 O(1) 平方阶
5log(2)n+20 O(logn) 对数阶
2n+3nlog(2)n+19 O(nlogn) nlogn阶
6n2+3n+4 O(n^3) 立方阶
2^n O(2^n) 指数阶