最近互聯網招聘平台拉勾網在五一期間推出個“最難面試的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
FizzFizz
Whizz
FizzBuzz
16
17
Fizz
19
Buzz
…一直到100
- 三個數都是個位數,這里也沒說是否包含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
當然不是一個.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(); }