1-2+3-4+5-6+7......+n的幾種實現


本文的內容本身來自一個名校計算機生的一次面試經歷,呵呵,沒錯,你猜對了,肯定 不是我吐舌頭

個人很喜歡這兩道題,可能題目原本不止兩道,當然,我這里這分析我很喜歡的兩道。

1.寫一個函數計算當參數為n(n很大)時的值 1-2+3-4+5-6+7......+n 
當我看了面試經過后,我覺得很有代表性,於是,我就拿着這個題目去問我的一些同學,我想看看大家拿到這個題目的第一實現方式。大家給我的反應也在意料之中,說是直接寫個for循環。自此,大家都犯了一個程序員最愛犯的錯誤,那就是把所有的工作都交給cpu去做。或許大家會說,現在的計算機,運行速度那么快,根本不用考慮執行這種程序給cpu帶來的效率問題。對於這個問題,我們下面在討論。

看這位名校生第一次給出的答案:

 

[cpp]  view plain  copy
 
 print?
  1. long fn(long n)  
  2. {  
  3.   long temp=0;  
  4.   int i,flag=1;  
  5.   if(n<=0)  
  6.   {  
  7.       printf("error: n must > 0);  
  8.       exit(1);  
  9.     }  
  10.   for(i=1;i<=n;i++)  
  11.   {  
  12.       temp=temp+flag*i;  
  13.       flag=(-1)*flag;  
  14.   }  
  15.       return temp;  
  16. }  


此答案面試官並不滿意,后來他又給出了第二個答案:

 

 

[cpp]  view plain  copy
 
 print?
  1. long fn(long n)  
  2. {  
  3.     long temp=0;  
  4.     int j=1,i=1,flag=1;  
  5.     if(n<=0)  
  6.   {  
  7.       printf("error: n must > 0);  
  8.       exit(1);  
  9.     }  
  10.     while(j<=n)  
  11.     {  
  12.       temp=temp+i;  
  13.       i=-i;  
  14.       i>0?i++:i--;  
  15.       j++;  
  16.     }  
  17.     return temp;  
  18. }   


我個人覺得對於一個剛畢業的大四面試者來說,已經很不容易,當然肯定有人能做的比這些更好,他把原代碼中用乘除的地方換成了加減法,我們知道計算機做加減比做乘除效率更高,因為很多計算機乘除會最終轉換成加減法來做。

 

面試官仍不滿意,但此時這名大四面試着着急之下想不到最佳方案了。只能求最優答案。

 

[cpp]  view plain  copy
 
 print?
  1. long fn(long n)  
  2. {  
  3.     if(n<=0)  
  4.   {  
  5.       printf("error: n must > 0);  
  6.       exit(1);  
  7.     }  
  8.   if(0==n%2)  
  9.   return (n/2)*(-1);  
  10.   else  
  11.   return (n/2)*(-1)+n;  
  12. }  


呵呵,我也很驚奇,的確,在n很大的時候,此算法不知要比上面的兩種算法強多少倍。

 

這就是為什么上面提到的,程序員不能把所有的工作都丟給計算機,計算機的cpu是給用戶用的,而不是給程序員用的。

"不要認為CPU運算速度快就 把所有的問題都推給它去做,程序員應該將代碼優化再優化,我們自己能做的決不要讓CPU做 ,因為CPU是為用戶服務的,不是為我們程序員服務的!”多么精辟的語言,我已經不想再說 什么了!

上面的算法我覺得已經很優了,但是我的一個同學給出了在上面算法的基礎上我認為更優的方法。

 

[cpp]  view plain  copy
 
 print?
  1. long fn(long n)  
  2. {  
  3.     if(n<=0)  
  4.   {  
  5.       printf("error: n must > 0);  
  6.       exit(1);  
  7.     }  
  8.   if(0==n%2)  
  9.   return (n>>1)*(-1);  
  10.   else  
  11.   return (n>>1)*(-1)+n;  
  12. }   

 

我們知道加減法效率比乘除的效率高,而移位運算在大多數情況下也是比加減的效率更高。

2.用一種技巧性的編程方法來用一個函數實現兩個函數的功能n為如:

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)實現,當flag為0時 ,實現fn1功能,如果flag為1時實現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][i]; 
}

呵呵,是不是很巧妙?典型的空間換時間的算法!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM