學好編程人人不能不看的好文章

[網絡轉摘]學好編程人人不能不看的好文章

1.面試經過  
大約在年前我接到了臺灣瑞晟(Realtek)蘇州公司的面試通知,通知我2月21日到蘇州工業園區面試,接到面試後的幾天我把一些專業課溫習了一遍,特別是C++和數據結構,由於大學幾年裏,我一直專研這些方面,加上通過了高級程序員的考試,對於一些常用的算法我差不多也達到了爛熟於胸的地步,當時的感覺是如果問了我這些方面的問題我應該是沒有問題的!  
  
21日那天我被安排在4:30面試,由一位技術人員單獨給我面試,在問了一些簡單的問題之後他給我出了一道編程題目,題目是這樣的:  
(由於具體面試的題目比較煩瑣,我將其核心思想提取出來分解成了兩個獨立的簡單的問題,有可能問題分解的不當,請大家見諒,實際面試了一個的問題但比其複雜很多,而且涉及一些高等數學變換)  
1) 寫一個函數計算當參數爲n(n很大)時的值  
1-2+3-4+5-6+7......+n  
哼,我的心裏冷笑一聲!沒想到這麼簡單,我有點緊張的心情頓時放鬆起來!  
於是很快我給出我的解法:  
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很大很大的時候這三個程序運行時間的差別簡直是天壤之別!當我剛想開口說點什麼的時候,他卻先開口了:“不要認爲CPU運算速  
度快就把所有的問題都推給它去做,程序員應該將代碼優化再優化,我們自己能做的決不要讓CPU做,因爲CPU是爲用戶服務的,不是爲我們程序員服務的!”多麼精闢的語言,我已經不想再說什麼了!接着是第二個問題:  
2),他要求我用一種技巧性的編程方法來用一個函數實現兩個函數的功能n爲如:  
fn1=n  
/2!+n/3!+n/4!+n/5!+n/6!  
fn2=n/5!+n/6!+n/7!+n/8!+n/9!  
現在用一個函數fn(int n,int flag)實現,當flag爲0時,實現fn1功能,如果flag爲1時實現fn2功能!他的要求還是效率,效率,效率!說實在話,如果我心情好的話我應該能給出一種比較好的算法,但我那時真的沒有什麼心思再想了,我在紙上胡亂畫了一些諸如6!=6*5!的公式後直截了當的跟他說要他給出他的答案!面試官也沒有說什麼,給出了他的思路:  
定義一個二維數組  
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];  
}  
最後得到計算值!呵呵,典型的空間換時間的算法!  
這些總共花了50分鐘的時間,還有十分鐘我就跟他很隨意的聊聊天,聊了一些編程以及生活的問題,那時的我已經很放鬆了,因爲我知道這次面試結果只有一個:失敗。5:30的時候面試官要我等通知,於是我離開了他們公司。這就是面試的整個經過!  
  
  
作者:金蝶中間件公司CTO袁紅崗  
  
不知不覺做軟件已經做了十年,有成功的喜悅,也有失敗的痛苦,但總不敢稱自己是高手,因爲和我心目中真正的高手們比起來,還差的太遠。世界上並沒有成爲高手的捷徑,但一些基本原則是可以遵循的。  
  
  1. 紮實的基礎。數據結構、離散數學、編譯原理,這些是所有計算機科學的基礎,如果不掌握他們,很難寫出高水平的程序。據我的觀察,學計算機專業的人比學其他專業的人更能寫出高質量的軟件。程序人人都會寫,但當你發現寫到一定程度很難再提高的時候  
,就應該想想是不是要回過頭來學學這些最基本的理論。不要一開始就去學OOP,即使你再精通OOP,遇到一些基本算法的時候可能也會束手無策。  
  
  2. 豐富的想象力。不要拘泥於固定的思維方式,遇到問題的時候要多想幾種解決問題的方案,試試別人從沒想過的方法。豐富的想象力是建立在豐富的知識的基礎上,除計算機以外,多涉獵其他的學科,比如天文、物理、數學等等。另外,多看科幻電影也是一個很好的途徑。  
  
  3. 最簡單的是最好的。這也許是所有科學都遵循的一條準則,如此複雜的質能互換原理在愛因斯坦眼裏不過是一個簡單得不能再簡單的公式:E=mc2。簡單的方法更容易被人理解,更容易實現,也更容易維護。遇到問題時要優先考慮最簡單的方案,只有簡單方案不  
能滿足要求時再考慮複雜的方案。  
  
  4. 不鑽牛角尖。當你遇到障礙的時候,不妨暫時遠離電腦,看看窗外的風景,聽聽輕音樂,和朋友聊聊天。當我遇到難題的時候會去玩遊戲,而且是那種極暴力的打鬥類遊戲,當負責遊戲的那部分大腦細胞極度亢奮的時候,負責編程的那部分大腦細胞就得到了充分的休息。當重新開始工作的時候,我會發現那些難題現在竟然可以迎刃而解。  
  
  5. 對答案的渴求。人類自然科學的發展史就是一個渴求得到答案的過程,即使只能?道答案的一小部分也值得我們去付出。只要你堅定信念,一定要找到問題的答案,你纔會付出精力去探索,即使最後沒有得到答案,在過程中你也會學到很多東西??br />   
  6. 多與別人交流。三人行必有我師,也許在一次和別人不經意的談話中,就可以迸出靈感的火花。多上上網,看看別人對同一問題的看法,會給你很大的啓發。  
  
  7. 良好的編程風格。注意養成良好的習慣,代碼的縮進編排,變量的命名規則要始終保持一致。大家都知道如何排除代碼中錯誤,卻往往忽視了對註釋的排錯。註釋是程序的一個重要組成部分,它可以使你的代碼更容易理解,而如果代碼已經清楚地表達了你的思想,就不必再加註釋了,如果註釋和代碼不一致,那就更加糟糕。  
  
  8. 韌性和毅力。這也許是"高手"和一般程序員最大的區別。  
A good programming is 99 weat and 1?offee。  
高手們並不是天才,他們是在無數個日日夜夜中磨練出來的。成功能給我們帶來無比的喜悅,但過程卻是無比的枯燥乏味。你不妨做個測試,找個10000以內的素數表,把它們全都抄下來,然後再檢查三遍,如果能夠不間斷地完成這一工作,你就可以滿足這一條。  


 

 

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