1.問題の説明
最初はオフになっている電球がn個あります。まず、すべての電球をオンにします。次に、1つおきの電球をオフにします。3回目のラウンドでは、3つおきの電球を切り替えます(オフの場合はオン、オンの場合はオフ)。n回目のラウンドでは、最後の電球のみを切り替えます。nラウンド後に電球がいくつあるかを調べます。
例:
n = 3の場合。
最初は、3つの電球が[オフ、オフ、オフ]です。
最初のラウンドの後、3つの電球は[オン、オン、オン]になります。
2回目のラウンドの後、3つの電球は[オン、オフ、オン]になります。
3回目のラウンドの後、3つの電球は[オン、オフ、オフ]になります。
電球が1つしかないので、1を返す必要があります。
電灯はn個あり、最初はすべて消灯しています。次に、n回の操作を実行する必要があります。
最初の操作は、各ライトのスイッチを押す(すべてオンにする)ことです。
2回目の操作では、2つのライトごとにスイッチを押します。つまり、2番目、4番目、6番目、8番目のライトのスイッチを押します。
3回目の操作では、3つのライトごとにスイッチを押します。つまり、3番目、6番目、9番目の...ライトのスイッチを押します。
この方法をn回目まで繰り返します。つまり、n番目のランプのスイッチを押すだけです。
次に、ライトの数を表す正の整数nを入力し、n回の操作後にこれらのライトがいくつ点灯するかを尋ねます。
2.暴力的な解決策
private static int buldSwitchForce(int n) {
boolean[] flags = new boolean[n];
for(int i=1; i<=n; i++) {
for(int j=1; j<=n; j++) {
if (i%j == 0) {
flags[i-1] = flags[i-1] == true ? false: true;
}
}
}
int count = 0;
for(boolean each: flags) {
if (each) count += 1;
}
return count;
}
強引な解決策は2レベルのループです。
最初のレベルのループはライトの数を表し、待機の状態はブール配列で記述されます。falseの場合はオフ、trueの場合はオンを意味します。
ループの2番目のレイヤーはk番目のループを表します。i%j == 0の場合、このライトのステータスが変化することを意味します。ライトの前の状態がオン(true)の場合は、オフ(false)にする必要があり、その逆も同様です。
最後に、アレイ内の真の状態の数、つまり、まだ点灯しているライトの数を数えます。
このアルゴリズムの時間計算量はO(n 2)O(n ^ 2)です。O (n2)。
3.より良い解決策
上記の暴力的な解決策は確かに私たちが望む最適な解決策ではありません。以下でより良い解決策を分析しましょう。
最初はあまり手がかりがないこのような状況では、一般的な再帰を使用するか、通常の方法を見つけて試すことができます
。n= 3とすると、最終結果は1で、最後に最初のライトだけが点灯します。 。
最初のラウンドでは、すべてのライトがオンになります。
第2ラウンドでは、2番目のライトがオフになりました。
第3ラウンドでは、第3ライトがオフになりました。
2 = 2 ∗ 1、3 = 3 ∗ 1 2 = 2 * 1、3 = 3 * 12=2∗1 、3=3∗1
n = 4とすると、最終結果は2になり、最後に2つのライトが点灯します。
最初のラウンドでは、すべてのライトがオンになります。
第2ラウンドでは、2番目と4つのライトがオフになりました。
第3ラウンドでは、第3ライトがオフになりました。
第4ラウンドでは、第4ライトがオフになりました。
2 = 2 ∗ 1、3 = ∗ 1、4 = 4 ∗ 1 = 2 ∗ 2 2 = 2 * 1、3 = * 1、4 = 4 * 1 = 2 * 22=2∗1 、3=∗ 1 、4=4∗1=2∗2
nから8になると、最終結果は常に2になります。9になると、最終結果は3になります。なぜなら9 = 1 * 9 = 3 * 3 = 9 1 * 9 = 3 * 39=1∗9=3∗3。
最初のオフから最後のnラウンドの終わりまでのライトは、多くの状態切り替えを経る必要があります。奇数回通過した場合は最後にオンになり、そうでない場合はオフになります。上記の導出によれば、数が完全な平方数であり、非反復因子の数が奇数であることを確認することは難しくありません。完全な平方数でない場合は、対数係数の積として確実に表現できるためです。
したがって、最終結果は次のように表すことができます。
private static int bulbSwitch(int n) {
return (int)Math.sqrt(n);
}
平方根を見つけるだけで十分なのはなぜですか?
9つのライトがあり、最終結果が3であるとします。オンになっている3つのライトは、1 = 1 ∗ 1、4 = 2 ∗ 2、9 = 3 ∗ 3 1 = 1 * 1、4 = 2 * 2、 9 = 3 * 31=1∗1 、4=2∗2 、9=3∗3これら3つなので、平方根を直接取ります。