最難面試的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);
        }
    }
}

 

輸出如下:

3 5 7
1
2
Fizz
4
Buzz
Fizz
Whizz
8
Fizz
Buzz
11
Fizz
Fizz
Whizz
FizzBuzz
16
17
Fizz
19
Buzz
FizzWhizz
22
Fizz
Fizz
Buzz
26
Fizz
Whizz
29
Fizz
Fizz
Fizz
Fizz
Fizz
Fizz
Fizz
Fizz
Fizz
Fizz
Buzz
41
FizzWhizz
Fizz
44
FizzBuzz
46
47
Fizz
Whizz
Buzz
Fizz
52
Fizz
Fizz
Buzz
Whizz
Fizz
58
59
FizzBuzz
61
62
Fizz
64
Buzz
Fizz
67
68
Fizz
BuzzWhizz
71
Fizz
Fizz
74
FizzBuzz
76
Whizz
Fizz
79
Buzz
Fizz
82
Fizz
FizzWhizz
Buzz
86
Fizz
88
89
FizzBuzz
Whizz
92
Fizz
94
Buzz
Fizz
97
Whizz
Fizz
Buzz
View Code

 

當然不是一個.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();
}

 

 

 


免責聲明!

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



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