数据结构和算法之时间空间复杂度(上)
上篇文章没看的话,这篇文章就别看了。
一、知识点
- 最好时间复杂度(best case time complexity)
- 最坏时间复杂度(worst case time complexity)
- 平均时间复杂度(average case time complexity)
二、案例
1、分析时间复杂度
利用上一篇学到的知识点,分析下面这段代码的时间复杂度是多少。
private int search(int array, int n, int x) {
int i = 0;
int pos = -1;
for (; i < n; i ++) {
if (array[i] == x) {
pos = i;
}
}
return pos;
}
这段代码要实现的功能是,在一个无序的数组(array)中,查找变量 x 出现的位置。如果没有找到,就返回 -1。时间复杂度很容易,T(n)=O(n)。
2、代码优化
细心的人会发现这段代码if里面没有break,意味着即使找到了合适的位置也依然会继续for到结束。我们修正下。
private int search(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;
}
3、再次分析时间复杂度
这时候时间复杂度是多少呢?这就需要区分不同的情况了
1.最好的情况就是第一次循环就匹配到了,然后进行了break。这时候T(n)=O(1)
2.最坏的情况就是最后一次循环才匹配到或者说根本没匹配到,这时候T(n)=O(n)
我简单粗暴的归纳为一句话:
既然有最好又有最坏,那就看最好的情况发生概率大还是最坏的情况发生的概率大,哪个概率大,那么平均时间复杂度就是哪个。比如上段程序的平均时间复杂度就是O(n)
有点过于简单粗暴,但是很实用。如果要细说,那涉及到概率论和加权平均等等各种数学知识,意义不大。
三、练习
1、代码
// 全局变量,大小为10的数组array,长度len,下标i。
int array[] = new int[10];
int len = 10;
int i = 0;
// 往数组中添加一个元素
private 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];
}
// new_array复制给array,array现在大小就是2倍len了
array = new_array;
len = 2 * len;
}
// 将element放到下标为i的位置,下标i加一
array[i] = element;
++i;
}
2、分析
答案:最好时间复杂度是O(1),最差时间复杂度是O(n), 平均时间复杂度是O(1)。
因为进入if条件的概率远小于不进入if条件的概率。所以平均时间复杂度取最好的时间复杂度O(1)(也就是if外的,if外的就是O(1),if内的是O(n))。