事后统计法:把代码跑一遍,通过统计、监控,就能得到算法执行的时间和占用的内存大小
弊端:
解决办法:需要一个不用具体的测试数据来测试,就可以粗略地估计算法的执行效率的方法
概述:所有代码的执行时间 T(n) 与每行代码的执行次数 n 成正比(算法的执行时间与数据规模之间的增长关系)
大 O 时间复杂度表示法:并不代表代码真正的执行时间,表示 代码执行时间与数据规模增长的变化趋势,也叫 渐进时间复杂度,简称 时间复杂度
时间复杂度分析方法
几种常见时间复杂度实例分析(多项式量阶 和 非多项式量级)
注意:当数据规模 n 越来越大时,非多项式量级算法的执行时间会急剧增加。非多项式量级只有两个:O(2n) 和 O(n!)
i = 1;
while(i <= n){
i = i*2;
}
// 时间复杂度:O(logn)
注意:对数阶时间复杂度表示法,可以忽略对数的底,统一表示为 O(logn)
概述:代码的复杂度由两个数据的规模来决定
int cal(int m , int n){
int sum1 = 0;
int i = 1;
for(;i<m;++i){
sum1 = sum1 + i;
}
int sum2 = 0;
int j = 1;
for(;j<n;++j){
sum2 = sum2 + j;
}
return sum1 + sum2;
}
注意:本算法无法使用 加法法则,因为我们无法断定 m 和 n 他们两个谁大谁小,所以时间复杂度就是O(m+n)
// 全局变量,大小为 10 的数组 array 长度 len 下标 i
int array[] = new int[10];
int len = 10;
int i = 0;
// 往数组中添加一个元素
void add(int element){
// 数组空间不够
if(i >= len){
// 重新申请一个 2 倍大小的数组空间
int new_array[] = new int[len*2];
// 把原来 array 数组中的数据依次 copy 到 new_array 中
for(int j = 0; j < len; ++j){
new_array[j] = array[j];
}
array = new_array;
len = 2*len;
}
// 将 element 放到下标为 i 的位置,下标 i 加一
array[i] = element;
++i;
}
最好情况时间复杂度:
我们可以看到,在 i = (0~len-1) 时,时间复杂度都是 O(1)
最坏情况时间复杂度:
如果在 i = len 时,时间复杂度为 O(len)
平均情况时间复杂度:
总共有 n+1 种情况
1*1/(n+1) + 1*1/(n+1)+...+n*1/(n+1) = 2n/(n+1)
O(1)
均摊情况时间复杂度:
前 n 种时间复杂度为 O(1) , 最后一种情况时间复杂度为 O(n),我们可以将 O(n) 平均分配给 前 n 种,
所以时间复杂度为 O(1)