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]; 
}

呵呵,是不是很巧妙?典型的空间换时间的算法!

posted @ 2016-03-14 15:13  caozengling  阅读(3924)  评论(0编辑  收藏  举报