算法的三重境界

算法,還是算法,不過這章的算法裏面,我們加入了數據結構的體驗。
本章兩個案例:一個面試的案例,另外一個還是面試的案例。
只不過,第一個是別人面試的案例,我在整理本書的時候發現,把他編寫了進來。
第二個,確確實實是我自己面試碰到的案例,當我用英語簡單的說出了這個算法之後,成功通過了面試。並感概良多。
 

 

好了,我們具體來談這兩個案例吧,每個案例的解答有三種答案,代表了三種境界,我給他們取了一個名字:
一個合格學生的解答;
一個優秀學生的解答;
一個工程師的解答。
 

 

第一個題目是:

1 寫一個函數計算當參數爲n(n很大)時的值 1-2+3-4+5-6+7......+n
看起來相當的簡單吧。
 

一個合格學生的解答

 

一般說來,任何一個C語言基礎還不錯的學生會做出來:
long fn(long n)
{
long temp=0;
int i,flag=1;
if(n<=0)
{
printf("error: n must > 0);
exit(1);
}
for(i=1;i<=n;i++)
{
temp=temp+flag*i;
flag=(-1)*flag;
}
return temp;
}
 

 

確實,這個程序執行結果肯定是沒有問題!但當n很大的時候我這個程序執行效率很低, 還記得我們前面講算法的案例嗎?會浪費很多的時間的啊。在嵌入式系統的開發中,程序的運行效率很重要,能讓CPU少執行一條指令都是好的。
 

一個優秀學生的解答

讓我們看看,一個優秀學生,爲了更好的節約計算資源,而給出的答案。
long fn(long n)
{
long temp=0;
int j=1,i=1,flag=1;
if(n<=0)
{
printf("error: n must > 0);
exit(1);
}
while(j<=n)
{
temp=temp+i;
i=-i;
i>0?i++:i--;
j++;
}
return temp;
}
比起上一個程序,這個程序將所有涉及到乘法指令的語句改爲執行加法指令,既達到要題目的要求而且運算時間上縮短了很多!而代價僅僅是增加了一個整型變量!
 

一個工程師的解答

不錯,第二個程序確實在效率上有的很大的提高!但是,你知道一個合格的工程師有更加嚴格的要求,我們看看工程師的答案吧:
 

long fn(long n)
{
if(n<=0)
{
printf("error: n must > 0);
exit(1);
}
if(0==n%2)
return (n/2)*(-1);
else
return (n/2)*(-1)+n;
}
 

對比一下,在n越來越大的時候這三個程序運行時間的差別簡直是天壤之別!
但如果你數論學得好,瞭解這個算法,直接就可以寫出第三個答案來。
 

第二個題目:

在一個很小的內存空間裏面,將北京某電話局的8位電話號碼排序。號碼在一萬個以內。
 

合格學生的答案:

在硬盤中找一個緩存空間,講一萬個號碼一一讀入,先比較第一位,然後比較第二位……用一個排序算法。
 

優秀學生的答案:

將電話號碼由字符串轉化爲自然數,比如88180675,轉化後,存儲空間,由8位字節,變成了2個字節,大大降低了存儲空間,然後排序。
 

工程師的答案:

在內存中開闢一個順序存儲空間,第一個字節的第一位(bit)表示:10000000,第二位(bit)表示10000001……,直到99999999,組成一個向量。然後將所有“bit”置零,開始讀電話號碼,有一個電話號碼,就把相應的位置改爲“1”,當電話號碼讀完的時候,在這個bit向量上,就自然把所有的電話號碼排序了。
一個電話號碼,8個字節,對應程序中一個bit,空間減少了64倍,更關鍵的是,排序代碼變得無比簡潔和簡單。
感謝我過去的經歷,我用ucOS/-II開發過程序,這個系統的優先級管理就是用的這個原理。當我面試碰到這個問題的時候,舉一反三,顯得非常簡單。
這個案例,我一直覺得是體現算法和數據結構的魅力的最好案例。你掌握了嗎?
 

 

好了,今天的作業題目是:
用一個函數實現兩個函數的功能。
fn1(n)=n/2!+n/3!+n/4!+n/5!+n/6!
fn2(n)=n/5!+n/6!+n/7!+n/8!+n/9!
現在用一個函數fn(int n,int flag)實現,當flag0時,實現fn1功能,如果flag1
實現fn2功能!
 

 

提示:空間換時間的算法
答案:
定義一個二維數組 float t[2][5]存入{{2!,3!,4!,5!,6!},{5!,6!,7!,8!,9!}}然後給出一個循環:
for(i=0;i<6;i++)
{
temp=temp+n/t[flag];
}
 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章