聲明
本文是博主在Coursera學習時所寫的學習筆記,如有錯誤疏漏還望各位指正。
歡迎交流討論
如果大家轉載,請註明本文地址!
簡介
1.分析算法的必要性
- 預測算法的性能
- 用於算法之間的比較
- 提供擔保(當數據量較大時,對性能的保證)
- 學習理論基礎
- 避免bug
2.如何分析算法
方法:
- 觀察特徵
- 基於觀察結果假設出數學模型
- 對假設出的模型進行預測
- 通過進一步的觀察證實假設
- 修改模型,直至假設與觀察結果一致
原則:
- 實驗必須是可重複的
- 假設必須是可證僞的
觀察
通過一個例子來介紹這部分
例子
問題:給定N個確定的數字,找出三個數字之和爲0的組合的個數
例如:
輸入:30,-20,-40,-10,40,0,10,5
因爲符合要求的組合爲4個
1. 30 -40 10
2. 30 -20 -10
3. -40 40 0
4. -10 0 10
所以輸出爲 4
解決算法
public static int count(int[] a)
{
int N = a.length;
int count = 0;
for (int i = 0; i < N; i++)
for (int j = i+1; j < N; j++)
for (int k = j+1; k < N; k++)
if (a[i] + a[j] + a[k] == 0)
count++;
return count;
}
這是算法採用的方式暴力破解,通過三重循環遍歷所有組合並檢測其和是否爲0
測試算法運行時間
不同輸入結果的運行時間
分析
通過對數運算對結果進行縮放,
其中
假設
講觀察結果和分析進行結合,做出假設
假設:運行時間
預測
N = 8000,T = 51.0s
N = 16000, T = 408.1s
觀察
加倍法預測
通過加倍法預測可以快速估算b
其中b =
注:此方法不可以確定加速因子
計算a:
取較大的N,進行測試得到a
影響因素
獨立因素:
- 輸入數據
- 算法
相關因素:
- 硬件:cpu,內存…
- 軟件:編譯器,解釋器…
- 系統:網絡,操作系統…
數學模型
影響一個算法運行時間的因素有很多,但歸根結底還執行的指令數與執行每條指令所需要的時間。分析算法時應該分析當算法運行時執行的指令數,並當輸入數據增多時,執行指令數的增長速率是怎樣的。
分析指令
int count = 0;
for (int i = 0; i < N; i++)
for (int j = i+1; j < N; j++)
if (a[i] + a[j] == 0)
count++;
上述代碼所需要執行的指令
- 賦值語句:
N+2 - 變量聲明:
N+2 - 小於比較:
12(N+1)(N+2) - 等於比較:
12N(N−1) - 數組訪問:
N(N−1) - 增量運算:
12N(N−1) ~N(N−1)
簡化
但是這種分析是很繁瑣且沒有意義的,下面我們對其進行簡化
- 建立代價模型:使用一些基本預算作爲計算運行時間的基礎。在此例中我們可以使用數組訪問作爲這種基本操作,換言之,當數組訪問次數越多時,我們就認爲運行時間越長。
- Tilde notation:忽略低階項,只保留最高項。
- 當N很大時,低階項何以忽略不計
- 我們不考慮當N很小時的算法性能
- ex:
N3+20N+16 ~N3 N3+N2+N/2 ~N3
經過簡化以後,對上述的雙重循環估算就可以表示爲
這樣就極大的提高了我們分析算法的效率
增長模型
常見的增長模型
舉例:
算法原理
Theory of algorithms
- Best case. Lower bound on cost.
- Worst case. Upper bound on cost.
- Average case. “Expected” cost.
Commonly-used notations
Θ(N2)
表示算法的一般成本在N2 左右
例如:10N2,5N2+22NlogN+3N,100N O(N2)
表示算法的上界成本是N2
例如:100N,22NlogN Ω(N2
表示算法的下界成本是N2
例如N2+22NlogN
內存
在程序運行時數據以二進制的形式存在於內存中,每個二進制位(bit)的值只能爲0或1,8個二進制位稱爲一個字節(byte)
1GB(Gigabyte) =
1MB(Megabyte) =
各類數據在內存中佔用的字節數
一維數組:
二維數組:
對象:
- object overhead:16bytes
- pading:填充適量空白字節使每個對象所佔的字節數爲8的倍數
舉個例子:
public class MysteryBox { // 16 (object overhead)
private final int x0, x1, x2, x3; // 16 (4 int)
private final boolean y0, y1, y2, y3; // 4 (4 boolean)
private final long z0, z1; // 16 (2 long)
private final double[] a = new double[72]; // 8 (reference to array)
// 600 (double array of size 72)
//4 (padding to round up to a multiple of 8)
} ----
共664字節