數據結構和算法之時間空間複雜度(上)
上篇文章沒看的話,這篇文章就別看了。
一、知識點
- 最好時間複雜度(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))。