大 O 时间复杂度实际上并不具体表示代码真正的执行时间,而是表示代码执行时间随数据规模增长的变化趋势,所以,也叫作渐进时间复杂度(asymptotic time complexity),简称时间复杂度。
时间复杂度分析
只关注循环执行次数最多的一段代码
intcal(int n){ int sum = 0; int i = 1; for (; i <= n; ++i) { sum = sum + i; } return sum; }
O(n)。
加法法则:总复杂度等于量级最大的那段代码的复杂度
intcal(int n){ int sum_1 = 0; int p = 1; for (; p < 100; ++p) { sum_1 = sum_1 + p; } int sum_2 = 0; int q = 1; for (; q < n; ++q) { sum_2 = sum_2 + q; } int sum_3 = 0; int i = 1; int j = 1; for (; i <= n; ++i) { j = 1; for (; j <= n; ++j) { sum_3 = sum_3 + i * j; } } return sum_1 + sum_2 + sum_3; }
O(n2)
乘法法则:嵌套代码的复杂度等于嵌套内外代码复杂度的乘积
intcal(int n){ int ret = 0; int i = 1; for (; i < n; ++i) { ret = ret + f(i); } } intf(int n){ int sum = 0; int i = 1; for (; i < n; ++i) { sum = sum + i; } return sum; }
intcal(int m, int n){ int sum_1 = 0; int i = 1; for (; i < m; ++i) { sum_1 = sum_1 + i; } int sum_2 = 0; int j = 1; for (; j < n; ++j) { sum_2 = sum_2 + j; } return sum_1 + sum_2; }
O(m+n)。
空间复杂度分析
voidprint(int n){ int i = 0; int[] a = newint[n]; for (i; i <n; ++i) { a[i] = i * i; } for (i = n-1; i >= 0; --i) { print out a[i] } }
// n 表示数组 array 的长度 intfind(int[] array, int n, int x){ int i = 0; int pos = -1; for (; i < n; ++i) { if (array[i] == x) pos = i; } return pos; }
O(n)
// n 表示数组 array 的长度 intfind(int[] array, int n, int x){ int i = 0; int pos = -1; for (; i < n; ++i) { if (array[i] == x) { pos = i; break; } } return pos; }
最好o(1)、最坏o(n)、平均o(n)
均摊时间复杂度
// array 表示一个长度为 n 的数组 // 代码中的 array.length 就等于 n int[] array = newint[n]; int count = 0; voidinsert(int val){ if (count == array.length) { int sum = 0; for (int i = 0; i < array.length; ++i) { sum = sum + array[i]; } array[0] = sum; count = 1; } array[count] = val; ++count; }
o(1) 课后思考
// 全局变量,大小为 10 的数组 array,长度 len,下标 i。 int array[] = newint[10]; int len = 10; int i = 0; // 往数组中添加一个元素 voidadd(int element){ if (i >= len) { // 数组空间不够了 // 重新申请一个 2 倍大小的数组空间 int new_array[] = newint[len*2]; // 把原来 array 数组中的数据依次 copy 到 new_array for (int j = 0; j < len; ++j) { new_array[j] = array[j]; } // new_array 复制给 array,array 现在大小就是 2 倍 len 了 array = new_array; len = 2 * len; } // 将 element 放到下标为 i 的位置,下标 i 加一 array[i] = element; ++i; }
o(1)
油管 Ravindrababu Ravula 时间复杂度
O(n)
publicvoidtimeComplex1(int n){ for (int i = 1; i <= n; i++) { System.out.println("time complex"); } }
O(n^2)
publicvoidtimeComplex2(int n){ for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { System.out.println("time complex"); } } }
o(sqrt(n))
publicvoidtimeComplex3(int n){ int sum = 0; for (int i = 1; sum <= n; i++) { sum = sum + i; System.out.println("time complex"); } }
i
sum
n
1
1
n
2
2+1
n
3
3+2+1
n
4
4+3+2+1
n
k
k+(K-1)+(K-2)+…+3+2+1
n
k
k(k-1)/2
n
推导k与n的关系 k(k-1)/2 = n 计算时间复杂度 o(sqrt(n))
publicvoidtimeComplex4(int n){ for (int i = 1; i * i <= n; i++) { System.out.println("time complex"); } }
i
i * i
n
1
1 *1
n
2
2*2
n
3
3*3
n
k
k*k
n
推导k与n的关系 k*k = n 计算时间复杂度 o(sqrt(n))
O(n^2)
publicvoidtimeComplex5(int n){ for (int i = 1; i <= n; i++) { for (int j = 1; j <= i; j++) { for (int k = 1; k <= 100; k++) { System.out.println("time complex"); } } } }
publicvoidtimeComplex6(int n){ for (int i = 1; i <= n; i++) { for (int j = 1; j <= i * i; j++) { for (int k = 1; k <= n / 2; k++) { System.out.println("time complex"); } } } }
publicvoidtimeComplex7(int n){ for (int i = 1; i <= n; i = i * 2) { System.out.println("time complex"); } }
k
i
n
1
2
n
2
2*2
n
3
222
n
k
2^k
n
推导k与n关系 2^k = n 计算时间复杂度 o(log(n))
publicvoidtimeComplex10(int n){ while (n > 1) { n = n / 2; } }
推导k与n关系n = 2^k 计算时间复杂度 o(log(n))
O((n^2)log(n))
publicvoidtimeComplex8(int n){ for (int i = n / 2; i <= n; i++) { for (int j = 1; j <= n / 2; j++) { for (int k = 1; k <= n; k = k * 2) { System.out.println("time complex"); } } } }
O(n(log(n)^2))
publicvoidtimeComplex9(int n){ for (int i = n / 2; i <= n; i++) { for (int j = 1; j <= n; j = 2 * j) { for (int k = 1; k <= n; k = k * 2) { System.out.println("time complex"); } } } }
O(nlog(n))
publicvoidtimeComplex11(int n){ for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j = j + i) { System.out.println("time complex"); } } }