最难面试的IT公司之ThoughtWorks代码挑战——FizzBuzzWhizz游戏

最近互联网招聘平台拉勾网在五一期间推出个“最难面试的IT公司”代码挑战活动,评选出了5个最难面试的IT公司,即:ThoughtWorks、Google、Unisys、Rackspace、Cypress Semiconductor。每个公司联合拉勾网推出代码挑战,针对每个挑战都可以提交我们自己的代码,如果通过代码测试,就会在后面几天收到相关公司的笔试、面试邀请,这些都不多说了,感兴趣的可以去官网看看。这些题目简约而不简单,也就是看上去十分的简单,但是做到尽善尽美难能可贵,这就是为什么面试难的原因,给你的题目非常简单,你自以为写的非常正确但最终还是被刷,似乎莫名其妙,其实你的代码漏洞百出。

 

比如ThoughtWorks推出的第一道代码挑战题如下:


  
  
  
  

你是一名体育老师,在某次课距离下课还有五分钟时,你决定搞一个游戏。此时有100名学生在上课。游戏的规则是:

1. 你首先说出三个不同的特殊数,要求必须是个位数,比如3、5、7。 2. 让所有学生拍成一队,然后按顺序报数。

3. 学生报数时,如果所报数字是第一个特殊数(3)的倍数,那么不能说该数字,而要说Fizz;如果所报数字是第二个特殊数(5)的倍数,那么要说Buzz;如果所报数字是第三个特殊数(7)的倍数,那么要说Whizz。
4. 学生报数时,如果所报数字同时是两个特殊数的倍数情况下,也要特殊处理,比如第一个特殊数和第二个特殊数的倍数,那么不能说该数字,而是要说FizzBuzz, 以此类推。如果同时是三个特殊数的倍数,那么要说FizzBuzzWhizz。 5. 学生报数时,如果所报数字包含了第一个特殊数,那么也不能说该数字,而是要说相应的单词,比如本例中第一个特殊数是3,那么要报13的同学应该说Fizz。如果数字中包含了第一个特殊数,那么忽略规则3和规则4,比如要报35的同学只报Fizz,不报BuzzWhizz。
 
现在,我们需要你完成一个程序来模拟这个游戏,它首先接受3个特殊数,然后输出100名学生应该报数的数或单词。比如,
 
输入
3,5,7
输出(片段)
1 2 Fizz 4 Buzz Fizz Whizz 8 Fizz Buzz 11 Fizz
Fizz Whizz FizzBuzz 16 17 Fizz 19 Buzz  …
一直到100

 
嗯,看上去十分简单的一道输出题,没涉及到什么重要的算法,纯考大家的思维缜密,作为菜鸟,我也看不透这里面蕴含了什么陷阱或技巧。
我的一般思路就是(相信大多数都是这个思路):
1. 针对输入有两个要求需要满足:
  • 三个数都是个位数,这里也没说是否包含0(0难道不是个位数?),而且这三个个位数并不一定是素数(质数),因此在判断倍数时要小心,不能对三个数的乘积直接求余。
  • 三个数都必须互不相同。

2. 对于报数条件,我们应该逆序处理,比如先判断条件5,再判断条件4,4里面也要逆序,先判断是否同时是三个特殊数的倍数,最后判断条件3,都不满足直接输出该数字,流程如下(假设当前数是n,三个数分别是num1,num2,num3):

  • 如果n中包含了num1,则直接输出“Fizz”,这里如何用程序判断一个整数是否包含一个数字也许也是个考查点,我用Java写的,为了简单,直接将n转换为String然后使用indexOf判断。
  • 如果n同时是num1, num2和num3的倍数,则输出“FizzBuzzWhizz”,如果是num1和num2的倍数,则输出“FizzBuzz”,如果是num2和num3的倍数,则输出“BuzzWhizz”,如果是num1和num3的倍数,则输出“FizzWhizz”。否则,就判断是否是单个num1或num2或num3的倍数,如果是就输出相应的字符串。
  • 如果上面都不满足,则直接输出n即可。

这样的思路写程序就非常的简单,如下(这是反例,是大多数人都会写的代码,相信也是ThoughtWorks公司最不想看到的代码):

import java.util.Scanner;

public class FizzBuzzWhizz {

    /**
     * @brief FizzBuzzWhizz game.
     */
    public static void main(String[] args) {

        Scanner in = new Scanner(System.in);
        int num1 = in.nextInt();
        int num2 = in.nextInt();
        int num3 = in.nextInt();

        while (num1 <= 0 || num1 >= 10 || num2 <= 0 || num2 >= 10 
                || num3 <= 0 || num3 >= 10 || num1 == num2 || num2 == num3
                || num1 == num3) {
            System.out.println("These three digits must be between 1 and 9 and also" +
                    "be different with each other, please input again.");
            num1 = in.nextInt();
            num2 = in.nextInt();
            num3 = in.nextInt();
        }
        
        for(int n = 1; n <= 100; n++) {
            if(String.valueOf(n).indexOf(num1 + 48) != -1)
                System.out.println("Fizz");
            else if(n % num1 == 0 && n % num2 == 0 && n % num3 == 0)
                System.out.println("FizzBuzzWhizz");
            else if(n % num1 == 0 && n % num2 == 0 )
                System.out.println("FizzBuzz");
            else if(n % num2 == 0 && n % num3 == 0)
                System.out.println("BuzzWhizz");
            else if(n % num1 == 0 && n % num3 == 0)
                System.out.println("FizzWhizz");
            else if(n % num1 == 0)
                System.out.println("Fizz");
            else if(n % num2 == 0)
                System.out.println("Buzz");
            else if(n % num3 == 0)
                System.out.println("Whizz");
            else
                System.out.println(n);
        }
    }
}

 

当然不是一个.java文件提交上去就可以了,为了体现严谨性,你还需要写环境说明、运行说明、单元测试等等。单元测试挺重要,能写出什么样的测试用例也能反映出你思维的缜密性,比如这里至少包括以下几个测试用例:

  • 输入中有负数、有0、有大于10的数、有相等的数,这时候的处理是全部重输还是不符合条件的重输,我这里选择的是全部重输。
  • 输入全部为素数、全部为合数、部分素数部分合数,体现你没有误解题目意思是全素数。

 

这是我也可能是大多数人一股脑的想法,当然题目本身没有这么简单,肯定还有许多我没有考虑到的地方,这里只是提供一个反例。

大家先别骂我的代码或骂这些公司出的这些题目,肯定有他们自己的道理,也许等我们看到大牛针对这样的需求写出不到10行的代码且复杂度最低,也许我们就知道原来他们想要的是这样的代码。

欢迎大家提出自己的宝贵意见和更好更轻的代码或想法,共同探讨这些大公司到底想要考我们什么东西。

 

------------------------------------------------------------------

更新:感谢网友@mringg提供了一个更简洁的代码,根据需求,完全不必按部就班的像我那样,如下的判断更好:

for(int n = 1; n <= 100; n++) {
    flag = true;
    if(String.valueOf(n).indexOf(num1 + 48) != -1) {
        System.out.println("Fizz");
        continue;
    }
    if(n % num1 == 0) {
        System.out.print("Fizz");
        flag = false;
    }
    if(n % num2 == 0) {
        System.out.print("Buzz");
        flag = false;
    }
    if(n % num3 == 0) {
        System.out.print("Whizz");
        flag = false;
    }
    
    if(flag)
        System.out.print(n);
    System.out.println();
}

你可能感兴趣的:(java,面试,单元测试,招聘,Thoughtworks)