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

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

  • 相关阅读:
    js——获取指定日期的前7天连续日期
    一个div自动充满当前屏幕的解决方法
    Cookie和Session
    Web服务器和浏览器间的工作原理
    软件测试基础概念
    K短路的几种求法
    ID字体
    搭建GitLab的Hexo博客记录
    项目selfcmp开发学习
    牛顿迭代法学习笔记
  • 原文地址:https://www.cnblogs.com/caozengling/p/5275822.html
Copyright © 2020-2023  润新知