大家好!這是我的第一篇博文,謝謝大家的支持!
(一)算法運行時間估計
估計某個算法的時間復雜度需要一些數學定義,如 T(N) = O(fn),表示T(N)的增長率小於等於fn; T(N) = Ω(fn),表示T(N)的增長率大於fn; T(N) = θ(fn),表示T(N)的增長率等於fn; T(N) = o(fn),表示T(N)的增長率小於fn. 我們一般考察O,即大O,時間上界.一個算法運行的時間進行估計,以便我們更好的了解程序設計與運行的優化方法.
估計法則1:
如果T1(N) = O(fn),t2(N) = O(gn),則有 T1(N)+T2(N) = max(O(fn),O(gn)) ,T1(N)*T2(N) = O(fn*gn)
估計法則2(循環):
一次循環的運行時間至多是循環體內語句運行時間乘以循環次數;嵌套循環為循環體內語句運行時間乘以各層循環次數之積.
估計法則3(順序結構):
順序結構運行時間等於各條語句運行時間之和.
估計法則4(分支結構):
分支結構運行時間不會大於分支中運行時間最長的那個分支體.
估計法則5(對數):
對數形式一般出現在 一個算法用常數時間將問題大小削減一半(或者有形如k *= 2的形式), 如二分查找
綜合以上法則,我們就可以分析出某個具體算法的時間上界
例:分析運行時間
1 Value = 0; 2 for( i= 1; i < N; i++) 4 for( j = 1;j < i*i; j++) 6 for( k = 0; k < j; k++) 8 Value++;
Value++的運行時間為常數階,第一層循環次數為N;第二層循環次數i*i與N2 有關,因為i與N有關.同理第三層循環次數j與N2 有關.則N*N2 *N2=N5,即O(N5)
(二)素數判斷算法
在程序設計的學習過程中,判斷一個數是否為素數的算法相信大家都非常熟悉了,這里與大家復習一下並提出更好的方案.
首先,什么是素數.素數就是除了1和它本身外,沒有其他因數的正整數.啊,將n從2除到√n,這是我的,相信也是很多人的第一想法.那么有沒有更好的方案吶?讓我們從頭開始.
嘗試1:
1 bool isPrime(int n){ 2 if(n <= 1) 3 return false; //1以及非正數不可能為素數,函數返回
4 for(int i = 2; i < n; i++){ //從2開始找到n-1
5 if(n%i == 0) 6 return false; //被整除代表有其他因數,這不是素數,函數返回
7 } 8 return true; //檢驗完畢,為素數,函數返回
9 }
這是最原始的算法,根據素數定義.容易得到,最壞情況比較要進行n-2次,時間復雜度為O(n).對於判斷一個大數的情況,顯然費時.
嘗試2:
1 bool isPrime(int n){ 2 if(n <= 1) 3 return false; 4 for(int i = 2; i <= (n/2); i++){ 5 if(n%i == 0) 6 return false; 7 } 8 return true; 9 }
因為一個數的因數總是成對出現(如2*3=6,2和3都是6的因數),且按這個數的中值對稱分布,因此只需要算到這個數的一半就行了.顯然,循環比較次數比嘗試1少,但時間復雜度仍為O(n).
嘗試3:
1 bool isPrime(int n){ 2 if(n <= 1) 3 return false; 4 for(int i = 2; i <= sqrt(n); i++){ 5 if(n%i == 0) 6 return false; 7 } 8 return true; 9 }
這個方法相信大家非常熟悉,也是最容易想到的.依據是若n有因數a和b,即n=a*b,那么必有一個因數位於2到√n之間,又因因數對稱且成對出現,那么檢驗范圍從2到√n就行了(我們當然可以檢驗√n到n-1),時間復雜度為O(√n)
嘗試4:
1 bool isPrime(int n){ 2 if(n == 2) //2是偶數中唯一的素數
3 return true; 4 if(n <= 1 || n%2 == 0) //除了2外,所有偶數都不是素數,至少有因數2
5 return false; 6 for(int i = 3; i <= sqrt(n); i+=2){ 7 if(n%i == 0) 8 return false; 9 } 10 return true; 11 }
注釋說的很清楚了.這個算法比嘗試3進一步減少了檢驗比較次數,時間復雜度為O(√n)
除了上面這些基本嘗試(特別是嘗試4,比較不錯了)外,還有其他算法,如使用素數表的拉賓米勒測試等,還有些算法就需要很多的數學知識了,額.
書籍推薦:
謝謝大家!轉載請注明出處,謝謝合作!