常見時間複雜度
最好、最壞、平均情況時間複雜度
int
factorial
(int n)
return sum;
}
上面是乙個階乘的函式,第二三行消耗兩個unit_time,四五行for語句消耗2n個unit_time,這個**的總執行時間t(n) = (2n + 2) * unit_time,我們只需要取其中最大量級,其時間複雜度為o(n)。
int
cal(
int n)
return sum;
}
上述**,我們在分析他的時間複雜度時,只需要取其中迴圈次數最多的一串**,就是for語句,其時間複雜度為o(n)。
int
cal(
int n)
int sum_2 =0;
int q =1;
for(
; q < n;
++q)
int sum_3 =0;
int i =1;
int j =1;
for(
; i <= n;
++i)
}return sum_1 + sum_2 + sum_3;
}
上述**總共有三個迴圈,第乙個迴圈100次,是乙個常量的執行時間,可以直接忽略,第二個迴圈n次,第三個迴圈n2次,這段函式量級最大的為n2,所以整段**的時間複雜度為o(n2)。
int
cal(
int n)
}intf(
int n)
return sum;
}
上述**有兩個函式,函式cal()呼叫函式f(),所以函式cal()的時間複雜度為t(n) = t1(n) * t2(n) = o(n*n) = o(n2)。
intf1(
)intf2(
)return sum;
}
上述**,函式f1()消耗3個unit_time,為常量,可以忽略,函式f2()檢視迴圈次數最多的,迴圈1000次也是乙個常量,同樣可以忽略,所以函式f1()、f2()的時間複雜度都為o(1)。
i=1;
while
(i <= n)
上述**,while是迴圈次數最多的一項,當i > n時結束迴圈,每經過一次迴圈i的值要乘以2,寫出來就是:2、22、23、24……2k,所以計算出2k = n,k的值就好, k = log2n,時間複雜度o(log2n),實際上不管是什麼數為底,如:log3n = log32 * log2n,log32為常量,可以忽略,最後都可以換算為o(log2n),所以在對數階時間複雜度的表示方法裡,我們忽略對數的「底」,統一表示為 o(logn)。
o(nlogn)就是將 o(logn) 迴圈了n遍,比如,歸併排序、快速排序的時間複雜度都是 o(nlogn)。
int
cal1
(int n)
return sum;
}int
cal2
(int n)
}return sum;
}
如上述**,函式cal1()迴圈n次,函式cal2()迴圈n2次,所以cal1()時間複雜度為o(n),cal2()時間複雜度為o(n2)。
int
cal(
int m,
int n)
int sum_2 =0;
int j =1;
for(
; j < n;
++j)
return sum_1 + sum_2;
}
在上述**中,有兩個迴圈,迴圈m次和n次,我們無法判斷m和n誰大誰小,所以沒法忽略其中乙個所以上述**時間複雜度為o(m + n)。
o(m*n)同理。
上述情況比較簡單,而實際的運算中,會有著各種各樣的問題,讓人難以判斷,比如下面這個查詢函式。
// n表示陣列array的長度
intfind
(int
array,
int n,
int x)
}return pos;
}
上述函式就不能單純使用之前的方法了,需要分情況而定,最好情況為查詢到第乙個就找到,break跳出,那麼時間複雜度為o(1)。最壞情況為查詢到最後乙個才找到,那麼時間複雜度為o(n)。
最好和最壞都是比較極端的情況下才會發生,所以我們需要使用平均時間複雜度。查詢陣列總共有n + 1種情況,查詢資料執行的次數為:1 + 2 + 3 + …… + n + n,總共 (1 + n) * 2 / n + n。最終可以得到時間複雜度為o(n)。
查詢數字不一定在陣列中所以會n + 1種情況,而這個概率也有一定的問題,能夠查詢到和不能查詢到的概率都應該為1 / 2,這樣數字出現在陣列中每乙個的概率就不應該是1 / n,而是1 / 2n。
這個值就是概率論中的加權平均值,也叫作期望值,所以平均時間複雜度的全稱應該叫加權平均時間複雜度或者期望時間複雜度。這樣最終的時間複雜度為o(n)。
// array表示乙個長度為n的陣列
// **中的array.length就等於n
int[
] array =
newint
[n];
int count =0;
void
insert
(int val)
array[0]
= sum;
count =1;
} array[count]
= val;
++count;
}
上述**是往陣列中插入資料,當資料插滿時(count == array.length),將陣列中所有數求和,放到陣列第乙個位置,並清空陣列。當陣列未滿,插入資料,時間複雜度為o(1),當陣列滿了,時間複雜度為o(n),可以使用之前的平均時間複雜度計算為o(1)。
這裡時間複雜度分析其實不用這麼麻煩,首先對比一下函式find()和insert()。
一、find()在極端情況下為o(1),而insert()在大部分情況下為o(1)
二、insert()中o(1)插入和o(n)插入是有規律的
所以針對這種比較特殊的情況,我們可以使用均攤時間複雜度,將那一次o(n)均攤到n - 1次o(1)上,這一組連續的操作的時間複雜度就為o(1)。
總之,對一組資料進行連續的操作,並且前後有著連貫的時序關係,這個時候我們就可以將這一組操作放在一起分析,看看能不能將那一次較高的時間複雜度操作均攤到其他較低的時間複雜度上面。
常見的複雜度,從低階到高階有:o(1)、o(logn)、o(n)、o(nlogn)、o(n2),我們需要根據複雜度選擇最合理的演算法。
演算法中時間複雜度分析
演算法的時間複雜度表示演算法執行所需要的時間 大o表示法 是一種體現演算法時間複雜度的記法,如果用n表示資料規模,那麼o f n 表示演算法說需要執行的指令數 消耗的時間 和 f n 成正比。大o表示法指出了演算法執行的最低上限。大o表示法的前邊省略了乙個常數 例子 有乙個字元陣列,將陣列中的每乙個...
演算法時間複雜度分析
定義 如果乙個問題的規模是n,解這一問題的某一演算法所需要的時間為t n 它是n的某一函式 t n 稱為這一演算法的 時間複雜性 求解演算法的時間複雜度的具體步驟是 1 找出演算法中的基本語句 演算法中執行次數最多的那條語句就是基本語句,通常是最內層迴圈的迴圈體。2 計算基本語句的執行次數的數量級 ...
演算法分析時間複雜度
對乙個演算法的分析,很多時候我們更關心演算法執行的時間複雜度。演算法的時間複雜度中,我們關心演算法執行的時間上界。即大o階分析方法。時間複雜度的分類 1 沒有迴圈遞迴的基本都是常數階。2 有一層迴圈的就是線性階。for int i 0 i dosth 3 對數階 一般類似如下 while i i i...