答えを出す
候補者が質問するほど興味を持っていなければ、息を無駄にしないと言いましたが、@ Yannis_Rizosの答えははるかに優れています。
インタビューのペースはかなり速い。面接後何日間もよく調べていることを知っています。
FizzBuzz Classicをコーディングできない人
大きなこだわりが%演算子を認識していると思います。誰かが比較したいと思う(myInt / 3) == (myDouble / 3.0)
かもしれないが、おそらくインタビューのストレスと... ヒントとして、半分クレジットの「Fizz」をコーディングし、後で拡張機能として「Buzz」を追加するように人々に頼んでみましたか?
あなたの質問に対する究極の答えは、良い候補者を見つけるのは本当に難しいということだと思います。
一般的なインタビューの質問
候補者に最後に興奮したプログラミングプロジェクトについて説明するよう依頼する方が簡単で生産性が高いことがよくわかりました。私はこの質問で100%成功しました。つまり、プログラミングプロジェクトについてアニメーションで話し、それについて技術的な質問に答えることができた人は、優秀な人材であり、できなかった人はそうではありませんでした。これには、候補者を安心させ、自由な議論を促すという素晴らしい副作用があります。この質問で、候補者は実際に、彼らが最も適しているものを教えてくれます。
シンクタンクアルゴリズムの質問も必要かもしれませんが、私は「お気に入りのプロジェクト」の質問に賛成してそれらを放棄しました。
FizzBuzzの合計(息子)
あなたのインタビューの質問はFizzBuzzと同等ではありません:
3または5の倍数である10未満のすべての自然数をリストすると、3、5、6、および9が得られます。これらの倍数の合計は23です。3または5のすべての倍数の合計を見つける関数を記述します1000未満。
FizzBuzz Classicでは、n回の反復(すべての数値またはFizz / Buzzを印刷する)を強制的に実行しますが、n / 5 + n / 3 + n / 15の反復で、または反復なしでも問題を解決できます。ポイント計算が可能です。次のプログラムは、これら3つの方法を比較します。
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のSumに対するブルートフォースソリューションはFizzBuzz Classicに似ていますが、Sum問題に対するより良い解決策が利用可能であり、根本的に異なる問題であることを示すことです。FizzBuzzの合計は、系列の合計の適切な式を覚えていない場合、または3または5ずつステップするときに適用されることに気付かない場合、非常に注意が必要です。
シリーズを半分に分割し、半分を逆にしてペアにすることでシリーズの合計の式を導出すると、(n + 1)(n / 2)が得られ、非常に厄介なパスをたどることができます整数除算と切り捨てられた剰余に関する限り。この式の(n(a1 + an))/ 2バージョンは、nのすべての値の単純な答えにとって絶対に重要です。