给出答案
我要说的是,如果候选人对问的兴趣不足,我不会浪费我的呼吸,但是@Yannis_Rizos回答要好得多。
面试非常快。我知道在面试后的几天里我经常会检查事情。
无法编写FizzBuzz Classic的人
我想象一个很大的症结在于意识到%运算符。您希望有人可以考虑比较(myInt / 3) == (myDouble / 3.0)
但也许会承受面试的压力……FizzBuzz Classic仍然采用蛮力方法,将其归类为最容易解决的算法问题。作为提示,您是否尝试过要求人们仅对“ Fizz”进行半信用编码,或者以后再添加“ Buzz”作为增强功能?
我认为您问题的最终答案是,很难找到优秀的候选人。
一般面试问题
我经常发现,让求职者描述他们兴奋的最后一个编程项目更容易,也更有效率。我在这个问题上取得了100%的成功,这意味着那些热衷于编程项目并可以回答有关该项目的技术问题的人才是伟大的员工,而不能做到的人却不是。这具有使候选人放心并鼓励开放式讨论的良好副作用。有了这个问题,候选人实际上将告诉您他们最适合的人选。
也许在智囊团中,算法问题也是必要的,但是我放弃了它们,转而使用“最喜欢的项目”问题。
FizzBuzz的总和(儿子)
您的面试问题不等同于FizzBuzz:
如果列出所有低于10的自然数,这些自然数是3或5的倍数,则得到3、5、6和9。这些倍数的总和为23。编写一个函数,求出3或5的所有倍数的总和。低于1000。
如果FizzBuzz Classic强迫您进行n次迭代(以打印出每个数字或Fizz / Buzz),则您的问题可以通过n / 5 + n / 3 + n / 15次迭代来解决,甚至可以不进行迭代-直接固定-点计算是可能的。下面的程序比较了这三种方法:
public static void main(String[] args) {
long n = Long.valueOf(args[0]).longValue();
long sum = 0;
long ms = System.currentTimeMillis();
// Brute force method Performance: cn
for (long i = 1; i <= n; i++) {
if ((i % 3) == 0) { sum += i;
} else if ((i % 5) == 0) { sum += i; }
}
System.out.print("Brute force sum: " + sum);
System.out.println(" time: " + (System.currentTimeMillis() - ms));
ms = System.currentTimeMillis();
// Second solution: iterate through only numbers we are
// interested in. Performance: c * (n/3 + n/5 + n/15)
// We counted multiples of 15 twice, so subtract one of them
sum = countSum(n, 3) + countSum(n, 5) - countSum(n, 15);
System.out.print("Only multiples sum: " + sum);
System.out.println(" time: " + (System.currentTimeMillis() - ms));
ms = System.currentTimeMillis();
// Third solution: Use high school algebra. Performance: c
sum = sumSeries(n, 3) + sumSeries(n, 5) - sumSeries(n, 15);
System.out.print("Sum of series: " + sum);
System.out.println(" time: " + (System.currentTimeMillis() - ms));
}
// Iteravely sum all multiples of skip
private static long countSum(long n, long skip) {
long skipTotal = skip;
long grandTotal = 0;
while (skipTotal <= n) {
grandTotal += skipTotal; skipTotal += skip;
}
return grandTotal;
}
// Thanks to @Caleb for pointing this out! High school algebra
// tells us that the sum of a series is: (n * (a1 + an)) / 2
// where a1 is the first term and an is the nth term. E.g. The
// sum of a series of 3 is: (n/3 * (3 + n - (n % 3))) / 2
// Since we are thinking about performance here, we'll shift
// right one instead of dividing by 2 for style points. ;-D
private static long sumSeries(long n, long skip) {
return (n/skip * (skip + n - (n % skip))) >> 1;
}
输出(FizzBuzz的总和<1000):
$JDK_HOME/bin/java FizzBuzzNot 999
Brute force sum: 233168 time: 0
Only multiples sum: 233168 time: 0
Sum of series: 233168 time: 0
使用较大的n进行性能比较:
$JDK_HOME/bin/java FizzBuzzNot 1000000000
Brute force sum: 233333334166666668 time: 4744
Only multiples sum: 233333334166666668 time: 818
Sum of series: 233333334166666668 time: 0
注意那些否定了这一点的人
提出此问题的解决方案的目的是表明,尽管FizzBuzz的总和的蛮力解决方案与FizzBuzz Classic相似,但仍存在针对Sum问题的更好的解决方案,这使它成为根本不同的问题。如果您不记得某个序列和的正确公式,或者不知道以3或5步进时,FizzBuzz的总和将非常棘手。
如果通过将序列分成两半,反转一半并将它们配对来重新推导一个序列总和的公式,则会得到(n + 1)(n / 2),这会使您陷入混乱就整数除法和截断的余数而言。此公式的(n(a1 + an))/ 2版本对于所有n值的简单答案绝对至关重要。