常用資料
算法複雜度
https://www.bigocheatsheet.com
動態演示站點
https://www.cs.usfca.edu/~galles/visualization/Algorithms.html
知識結構
算法5大特徵
有窮,確切,輸入項,輸出項,可行性
時間複雜度:
執行算法所需要的計算工作量
一般來說,計算機算法是問題規模n的函數f(n)
,算法的時間複雜度因此記做T(n)=O(f(n))
問題的規模越大,算法執行的時間的增長率與f(n) 的增長率正相關,稱作漸進時間複雜度(Asympotic Time Complexity)
計算方式:
- 1.計算次數公式
1+2+3+.......+n;
<?php
$sum=0;
for($i=1;$i<=$n;$i++){
sum+=$i;
}
?>
計算n次,時間複雜度爲O(n)
- 2.用常數1來取代所有時間中所有加法常數 比如O(3) 記做O(1)
<?php
function test($n){
echo $n;
echo $n;
echo $n;
}
?>
O(3) 記做O(1)
- 3.在修改後的運算次數函數中,只保留最高階項
n^2+n+1 則記做O(n^2) - 4.如果最高階存在且不是1,則去除與這個項相乘的常數
2n^2+3n+1 記做O(n^2)
常數階:O(1)
線性階:O(n)
平(立)方階:O(n^2),O(n^3)
<?php
$sum=0;
for($i=1;$i<=$n;$i++){
for($j=1;$j<=$n;$j++){
$sum+=$j;
}
}
?>
兩層循環 O(n^2) 三層O(n^3)
特殊平方階:O(n^2/2+n/2)-> O(n^2)
for(){
for(){
}
}
for(){
}
echo $a+$b;
n^2+n+1->O(n^2)
對數階
$i=1;$n=100;
while($i<$n){
$i=$i*2;
}
2^x=n
x=\log_2^n
\log_2^n=\log_2^{10}\log{n}
3^x=n
x=\log_3^n
\log_3^n=\log_3^{10}*\log{n}
最壞情況:最壞情況下的運行時間,一種保證,如果沒特殊說明,說的時間複雜度即爲最壞情況下的時間複雜度
平均情況:期望的運行時間
空間複雜度:算法需要消耗的內存空間,記作S(n)=O(f(n))
- 包括程序代碼所佔用的空間
- 輸入數據所佔用的空間和
- 輔助變量所佔用的空間
這3個方面
計算和表示方法與時間複雜度類似,一般用複雜度的漸進性表示
時間複雜度分析
1. 只關注循環執行次數最多的一段代碼
大 O 這種複雜度表示方法只是表示一種變化趨勢。
我們通常會忽略掉公式中的常量、低階、係數,只需要記錄一個最大階的量級就可以了。所以我們在分析一個算法、一段代碼的時間複雜度的時候,也只關注循環執行次數最多的那一段代碼就可以了
C是常數,爲何C能省略呢
Cn^2
C(n+1)^2-Cn^2=C(2n+1)
(n+1)^2-n^2=2n+1
2. 加法法則:總複雜度等於量級最大的那段代碼的複雜度
3. 乘法法則:嵌套代碼的複雜度等於嵌套內外代碼複雜度的乘積
空間複雜度分析
時間複雜度的全稱是漸進時間複雜度,表示算法的執行時間與數據規模之間的增長關係。類比一下,空間複雜度全稱就是漸進空間複雜度(asymptotic space complexity),表示算法的存儲空間與數據規模之間的增長關係。
void print(int n) {
int i = 0;
int[] a = new int[n];
for (i; i <n; ++i) {
a[i] = i * i;
}
for (i = n-1; i >= 0; --i) {
print out a[i]
}
}
跟時間複雜度分析一樣,第 2 行代碼中,我們申請了一個空間存儲變量 i,但是它是常量階的,跟數據規模 n 沒有關係,所以我們可以忽略。第 3 行申請了一個大小爲 n 的 int 類型數組,除此之外,剩下的代碼都沒有佔用更多的空間,所以整段代碼的空間複雜度就是 O(n)。