写这篇文章主要是因为偶然看到一篇关于stackoverflow公司的面经中提到了一个有趣的面试编程问题,如题所述:FizzBuzz问题。原文引用如下:

“在一些公平的考验之后,我发现那些因为代码而抓狂的人不是为了庞大的项目,而是在细小的地方就缠不休。所以我开始研究这些问题,收集这些编程人员的特点 和归结成一类问题,取名为“FizzBuzz 问题”。 FizzBuzz问题是一种英国学校学生经常玩的游戏。举个“FizzBuzz 问题”的例子:

写一个程序打印1到100这些数字。但是遇到数字为3的倍数的时候,打印“Fizz”替代数字,5的倍数用“Buzz”代替,既是3的倍数又是5的倍数打印“FizzBuzz”。

大部分优秀的程序员都应该能在纸上轻易地把这个程序写出来,也就几分钟的事情。但你想知道一个令人震惊的事实吗?多数计算机科学专业的毕业生不会做这道题。我还见过一个自称是高级程序员的人做这道题,他居然花了10~15分钟。

Dan Kegel在招聘初级程序员的时候,也经历了类似的事情:令人惊讶的是,有相当一部分的应聘者(包括那些获得计算机科学专业的硕士或博士学位的人),当他们被要求完成一个基本的编程任务时,他们都通不过,因此面试失败。举例来说,我曾经碰到过一些毕业生,他们居然回答不出"写一个从1数到10的循环"或者"在16进制里F后面的数是什么"之类的问题。如果务实一点,我在面试中也碰到过很多应聘者,他们不会用递归去解决一个实际的问题。但这些都是基本的技能。如果他们不会,只能说明他们很可能根本就没写过程序。

乍看这个问题的时候感觉题目叙述很清楚啊,思路也很简单啊,比现在很多公司用的字符串逆序,字符串空格替换啥的简单多了啊,为什么还会如此火地作为一个面试编程题?自己动手写了个,1分钟搞定,没毛病。然后怀着疑问就去百度了下,还真有各种论坛博客等网站都在讨论怎么写。然后看了下那些不屑一顾的编程爱好者们贴出来的代码,看完大家的代码后,我的内心是崩溃的,终于知道为什么这也能作为程序员们的面试编程题目了

  看到这里的你不妨也去写一写吧,说不定写的过程中也会发现联想起来很多有趣的事呢)。

  不知道为什么常逛CSDN的那些技术宅们,为何会给出这样奇葩的答案,再次刷新了我对CSDN的用户平均技术水平,下面把几种CSDN论坛里网友给出的答案并且在真实面试中很多人都容易犯的毛病提出来吧,希望即将面试中要手写代码的亲多留意下这些问题:

  

  大哥你这是用python吗,给个语言提示啊。而且这是要手动从1打印到100?说好的3和5的控制呢?再说python是不需要分号的啊,你开头加后面又不加是什么编码风格?

  

  真不知道这哥们儿又是什么心态?(注:这两个答案是最先回复的,而且还得到了分数!)从代码风格来看,我感觉是完全从上面那答案复制,然后把print改成了cout>>了,对,你没有看错!是>>而不是<<,我真想问问这哥们儿,你真学过C++没?而且先不说你们俩都没有实现题目的需求,别人python不写分号没毛病,你这最后一句不写就有点尴尬了啊。

  

  好吧,终于算是一个看起来比较正常的代码了,眼前一亮,好欣慰。可是!我随便带一个数15进去,发现输出完全不对啊?这个代码会输出Fizz-Buzz \n Fizz \n Fizz-Buzz \n Buzz啊?这只有if没有else的代码看起来还是不靠谱,好吧,这个人估计到了面试也会倒下...  

  嗯哼,这个代码还算不错,验证结果也是正确的。不过啊,难道没有代码规范意识?三目运算符“?:”在一条一句里用了三次也是蛮佩服的,但是如果是公司的线上代码写成这样会被人嫌弃得要死吧!真是印证了那句“***的裹脚布,又臭又长”

  

  一眼看过去,第一:不符合题意要求,明明要求的是如果是*的倍数,只输出单词即可,为何要自作主张输出数字加冒号?这是面试中的大忌讳,切记不可自以为是的修改了“用户需求”。第二:这明显是把特殊case处理了,普通case给直接漏掉了啊?结果自然就不对了

  

  哇,好工整,好想来句赞,可是......为什么是range(1,100)?你是对题意没理解清楚还是不知道range的具体用法呢?另外,其中三处continue实乃画蛇添足!

  

  看到第一句,就有点心累,又是范围问题,题目中明确说了是1~100的数字,怎么变成[0,100)区间了呢?而且中间有明显的冗余判断:如果进了else if(i%5--0)这个条件里,就不可能进入里面一层的if(i%3==0)好吧?

  

  我勒个去?我都开始怀疑这个人为何要加入CSDN了,如果题目突然换成1000,100000了,你也手算?

  

  哇,竟然看到了有人用js来提交,仔细一看。。顿时失望了。第一,还是范围问题。第二,思路倒是没问题啊,对倍数进行重新赋值,可是,那个len=15那里,为什么还是赋值为Fizz?题目没看清还是手抖了?另外,效率较低。

  

  经验证,这个代码可以满足需求,终于算是看到了一个能pass的代码了。不过,这个需要半个小时?有点接受不了。而且这代码格式,看了让人落泪,听了让人疯狂

  

  最后贴一个,这个实在是胆小精悍,乍一看还以为没实现,不过看起来不明觉厉,就去验证了下,发现!!!除了0也被包含进来(范围问题)之外,竟然完全正确,实在是python大法好啊!仔细看了下,如果真的面试中就写了这一句给面试官,并且搭配上准确的解释那也将是完美的通过面试节奏。这一句里面涉及到的知识点有:for in语法、range函数(另外,为什么不用xrange呢岂不更好)、[::]。将自己对这三个语法知识点的理解和延伸说说,将让面试官心服口服!


  当然,上面很多代码是很直接的硬伤,连基本需求都过不了,作为要去面试的人来说,这道题如果写不出满足基本需求的代码,感觉有点过分啊!

  不过我觉得如果想作为一个合格的工程师(好吧,如果你想称呼自己为程序员...开心就好),这个基本需求还远远不够,因为工作中的实际需求比这个不知道要复杂多少倍!

  从这题来说的话,需要说的点还有:拓展性效率问题。

  也许只从这100个数来看,对效率问题可能不会有什么要求,总是要遍历的嘛,而且就100个数,效率影响因子基本可忽略。但是如果把这个问题拓展到实际环境,这个100可能被瞬间变为100亿,同样这个过程也可能重复运行上亿次,这个时候,我们就不得不考虑效率问题了。

  对于拓展性,这里很简单,就是把那个magic number(100)拿出来当做函数的参数(面试中给的编程题都最好写成函数的形式,哪怕只是一段简短的代码!既然是个函数,就要注意函数参数和返回值问题等等),这样就可以根据实际情况来确定数据范围。

  效率的话,当然是冗余判断次数越少越好,充分利用已有条件来减少判断次数。 下面是以C语言为例的示例代码:

  1. void printFizzBuzz(int n=)
  2. {
  3. for (int i = ; i <= n; ++i)
  4. {
  5. if (i % == )
  6. {
  7. if(i % == )
  8. printf("FizzBuzz\n");
  9. else
  10. printf("Fizz\n");
  11. }
  12. else if (i % == )
  13. {
  14. printf("Buzz\n");
  15. }
  16. else
  17. {
  18. printf("%d\n", i);
  19. }
  20. }
  21. }

  对于效率问题,这个代码中,每个数进来都只会判断两次并打印出结果。而对比上面贴出的CSDN网页们的答案,很多答案将会有更多次判断。

  其实问题可以再严肃一点:每个输出之间的间隔符题目中没有明确规定,但是不代表没有,上面有些答案中并没有输出分隔符,这也算是一个问题吧,上面我提供的这个代码中是以换行作为分隔的,如果是要以空格分隔,并且最后一个结果后面不加分隔呢?如果要每k个数用\n分隔,k个数之间用空格分隔呢?这些就变得稍微复杂了,更能考验面试者的严谨性、编码能力、编码风格和思维方式了。

  另外,对于擅长不同编程语言的人来说,可能会用不同的语言来实现,那么如果是你,你会用多少种较主流的语言来完整且正确的写出这个问题的答案呢?

  最后,我不得不承认,这真的是一个考验面试者的编程能力的好问题!


  本文经过分析CSDN相应帖子后整理得出,转载请注明出处-“闻波 博客园”:http://www.cnblogs.com/webary/p/6507413.html

简单却又复杂的FizzBuzz面试编程问题的更多相关文章

  1. 简单介绍Javascript匿名函数和面向对象编程

    忙里偷闲,简单介绍一下Javascript中匿名函数和闭包函数以及面向对象编程.首先简单介绍一下Javascript中的密名函数. 在Javascript中函数有以下3中定义方式: 1.最常用的定义方 ...

  2. 经典面试编程题--atoi()函数的实现(就是模拟手算,核心代码就一句total = 10 * total + (c - '0'); 但是要注意正负号、溢出等问题)

    一.功能简介 把一个字符串转换成整数 二.linux c库函数实现 /*** *long atol(char *nptr) - Convert string to long * *Purpose: * ...

  3. 面向面试编程——javascript对象的几种创建方式

    javascript对象的几种创建方式 总共有以下几个模式: 1.工厂模式 2.构造函数模式 3.原型模式 4.混合构造函数和原型模式 5.动态原型模式 6.寄生构造函数模式 7.稳妥构造函数模式 1 ...

  4. java面试编程题

      [程序1]   题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?   //这是一个菲波拉契数列问 ...

  5. 【剑指Offer面试编程题】题目1360:乐透之猜数游戏--九度OJ

    题目描述: 六一儿童节到了,YZ买了很多丰厚的礼品,准备奖励给JOBDU里辛劳的员工.为了增添一点趣味性,他还准备了一些不同类型的骰子,打算以掷骰子猜数字的方式发放奖品.例如,有的骰子有6个点数(点数 ...

  6. 【剑指Offer面试编程题】题目1362:左旋转字符串--九度OJ

    题目描述: 汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果.对于一个给定的字符序列S,请你把其循环左移K位后的序列输出.例如,字符序列S=&qu ...

  7. 【剑指Offer面试编程题】题目1504:把数组排成最小的数--九度OJ

    题目描述: 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个.例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323. 输入: 输 ...

  8. 【剑指Offer面试编程题】题目1524:复杂链表的复制--九度OJ

    题目描述: 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点). 输入: 输入可能包含多个测试样例,输入以EOF结束. 对于每个测试案例,输入的第 ...

  9. 【剑指Offer面试编程题】题目1521:二叉树的镜像--九度OJ

    题目描述: 输入一个二叉树,输出其镜像. 输入: 输入可能包含多个测试样例,输入以EOF结束. 对于每个测试案例,输入的第一行为一个整数n(0<=n<=1000,n代表将要输入的二叉树节点 ...

随机推荐

  1. Delphi中ShellExecute的妙用

    ShellExecute的功能是运行一个外部程序(或者是打开一个已注册的文件.打开一个目录.打印一个文件等等),并对外部程序有一定的控制.有几个API函数都可以实现这些功能,但是在大多数情况下Shel ...

  2. Linux 系统分区

    合理的系统分区,便于后期管理和提高文件的搜索速度 分区格式说明 linux分区不同于windows,linux下硬盘设备名为(IDE硬盘为hdx(x为从a—d)因为IDE硬盘最多四 个,SCSI,SA ...

  3. LazyInitializationException--由于session关闭引发的异常

    1,页面中进行person.department.departmentName的读取 2,Action 中只读取了person,事务作用在Service的方法中 3,后台会有org.hibernate ...

  4. python enhanced generator - coroutine

    本文主要介绍python中Enhanced generator即coroutine相关内容,包括基本语法.使用场景.注意事项,以及与其他语言协程实现的异同. enhanced generator 在上 ...

  5. 【python基础】 Tkinter 之 几何管理器

    Tkinter支持三种几何管理器:网格管理器,包管理器,位置管理器 提示:由于每个管理器都有自己放置小构件的风格,最好不要在同一个容器中的小构件使用多个管理器.可以使用框架作为子容器以获取期望的布局. ...

  6. Intellij IDEA 建立文件夹目录问题

    问题: NEW一个package常出现文件夹层次问题 解决: 1.选中当前文件夹(要在该文件夹下添加): 2.右击此处: 3.添加即可. 链接:http://stackoverflow.com/que ...

  7. Hadoop权威指南:HDFS-写入数据

    Hadoop权威指南:HDFS-写入数据 FileSystem类有一系列的新建文件的方法.最简单的方法是给准备建的文件指定一个Path对象,然后返回一个用于写入数据的输出流: public FSDat ...

  8. 《JAVASCRIPT高级程序设计》第五章(2)

    一.Date类型 Date类型类型用于保存日期,有以下几种创建方式: //获取当前时间 var now = new Date(); //获取当前时间的毫秒数 var nowSecond = Date. ...

  9. Windows 10 IoT Serials 5 - 如何为树莓派应用程序添加语音识别与交互功能

    都说语音是人机交互的重要手段,虽然个人觉得在大庭广众之下,对着手机发号施令会显得有些尴尬.但是在资源受限的物联网应用场景下(无法外接鼠标键盘显示器),如果能够通过语音来控制设备,与设备进行交互,那还是 ...

  10. [Bullet3]常见物体和初始化

    官方文档:http://bulletphysics.org 开源代码:https://github.com/bulletphysics/bullet3/releases API文档:http://bu ...