「我的程式會執行多長時間?為什麼我的程式耗盡了所有記憶體?」
在我們使用計算機解決困難問題或是處理大量資料時,不可避免地會產生這些疑問。為這些基礎問題給出答案有時其實非常簡單,這個過程是科學方法,這就是我們今天討論的內容。
科學方法概述:
科學家用於觀察世界的方法對於研究電腦程式一樣有效:
1.觀察真實世界特點
2.提出假設模型
3.根據假設模型**未來事件
4.繼續觀察並核實**的準確性
5.如此反覆直至確認**與觀察一致
正如愛因斯坦所說:「再多的實驗也不一定能夠證明我是對的,但只需要乙個實驗就能證明我是錯的」。科學方法的一條關鍵原則是我們所設計的實驗必須是可重現的,我們提出的假設也必須是可證偽的。我們永遠無法知道某個假設是絕對正確的,我們只能驗證他和我們觀察的一致性。
舉例:
這裡我們編寫了乙個threesum的程式,用於統計所有和為0的三整數元組的數量。示例**使用最簡單的暴力演算法,我們通過對其分析,可以進一步的優化,並了解演算法分析的過程。
publicclass
threesum
}
這裡我們同時會問我們的程式會執行多久,我們可以自己編寫乙個近似計時器,用於度量程式執行時間,使用系統api實現起來很簡單.
(1)觀察
我們使用多組不同規模的資料輸入進上述程式,統計其所耗費時長。根據統計的資料繪製圖表,根據圖表做出相應分析。
資料:2500.0
5000.0
1000
0.12000
0.84000
6.48000
51.1
...
實際繪製出影象符合對數曲線特點,我們由此可以猜測關於時間的規律
lg(t(n))=3lgn + lg(a)
~t(n)=an^3
根據影象資料可以計算出以下公式:
t(n)=9.98*(10^-11)*(n^3)
據此,我們可以做出**,當n=16000時,程式的執行時間約為6.8分鐘
(2)驗證
上面做出的猜測需要我們實際執行驗證,並多次檢驗實際執行結果是否符合**結果。
(3)結論
我們多次執行後發現,實際執行結果近似**結果,統計的對數影象中的直線完全符合我們對資料符合公式t(n)=an^3的猜想。
(4)總結
到現在為止,我們分析程式執行時長規律的過程與科學家們嘗試理解真實世界奧秘時進行的過程完全相同,我們稱以上公式為冪次法則。事實上,許多自然和人工現象都符合冪次法則,因此假設程式執行時間符合冪次法則也是合理的。對於演算法的分析,我們有許多數學模型強烈支援這種函式和其他類似的假設,我們會經常接觸並學習到它們。
演算法優化
現在我們分析了演算法的執行規律,下面會根據總結歸納的資訊對演算法進行相應地優化工作。
d. e. knuth認為乙個程式執行的總時間主要和兩點有關:
執行每條語句的耗時;
執行每條語句的頻率;
前者取決於計算機,編譯器和作業系統,後者取決於程式本身和輸入。如果程式的所有部分性質我們都知道,就可以將它們相乘並將程式的所有指令成本相加得到最終的總執行時間。
剛才我們討論的threesum程式中if語句的執行次數為:
n(n-1)(n-2)/6=1/6*n^3 +1/2*n^2 +n/3
一般在這裡,首項之後的其他項都相對較小,所以可以使用近似的方式忽略那些非常複雜但冪次較低,對最終結果貢獻無關緊要的項。
所以threesum程式的增量級為立方級別,同時這個規律和機器無關,只由其演算法本身決定。可以預料的是在任何計算機上使用任何語言實現的該演算法的實現所需執行時間都是和n^3成正比的。實際上,經典演算法的大部分效能理論大部分都發表於數十年前,但它們仍適用於今天的計算機。
下面是對一些常見演算法的增長數量級的總結
描述 增長的數量級 典型** 說明常數級別
1 a=b+c 普通語句
對數級別 logn 二分查詢演算法 二分策略
線性級別 n for迴圈 迴圈
線性對數級別 nlogn 歸併排序 分治
平方級別 n^2
雙層迴圈
立方級別 n^3
三層迴圈
指數級別
2^n 窮舉法 窮舉查詢
根據以上總結的資料,我們可以將threesum程式設計為更快地演算法,將其增量級從現有的n^3減小至(n^2)*logn .實現**如下:
publicclass
threesum
//二分查詢演算法
private
static
int rank(int key, int a, int lo, int
hi)
}
我們已知二分查詢演算法的增量級別為logn, 所以可以將第三個for迴圈替換為對a[i]+a[j]和的相反數的查詢,如果查詢到即三元組數量加一。最終我們可以觀察到新演算法的結果和原來的暴力演算法結果一樣正確。
至於是否還會有更快地演算法形式,我的回答是不知道,不過專家們相信three-sum可能的最優演算法是平方級的。
到此本篇部落格內容講述完畢,帶來的雖然是入門級的知識,但是所使用的方法適用於我們以後對任何高深演算法的研究和優化。
演算法手記(4)演算法分析
我的程式會執行多長時間?為什麼我的程式耗盡了所有記憶體?在我們使用計算機解決困難問題或是處理大量資料時,不可避免地會產生這些疑問。為這些基礎問題給出答案有時其實非常簡單,這個過程是科學方法,這就是我們今天討論的內容。科學方法概述 科學家用於觀察世界的方法對於研究電腦程式一樣有效 1.觀察真實世界特點...
演算法分析4
1.題目描述 對於表示式n2 n 41,當n 在 x,y 範圍內取整數值時 包括 x,y 39 x,y 50 判定該表示式的值是否都為素數。輸入 輸入資料有多組,每組佔一行,由兩個整數x,y組成,當 x 0,y 0 時,表示輸入結束,該行不做處理。輸出 對於每個給定範圍內的取值,如果表示式的值都為素...
《演算法分析》作業4
對n個不同的數構成的陣列 a 1.n 進行排序,其中 n 2 k,要求用歸併排序進行排序。歸併排序 當我們要對陣列進行排序的時候,我們首先把這個陣列分成一半,然後就是對左邊的陣列和右邊的陣列分別進行排序,之後將他們合併起來,然而對左右兩邊陣列進行排序的時候要用到分治的思想,對左右兩個陣列進行歸併排序...