The Bulb Switcher problem asks: Given n
bulbs that are initially off, you perform n
rounds of toggling bulbs. In the i
-th round, every bulb that is a multiple of i
(1-indexed) is toggled (on to off or off to on). After all rounds, return the number of bulbs that remain on.
1 <= n <= 109
n
.n
due to performance constraints.At first glance, it may seem natural to simulate the toggling process for each bulb and each round. However, with constraints up to 109, brute-force is not practical. Instead, we seek a mathematical pattern or shortcut.
Let's consider toggling: A bulb at position k
is toggled every time i
divides k
. Thus, the number of times a bulb is toggled is equal to the number of divisors of its position number. If a bulb is toggled an odd number of times, it ends up on; if even, it ends up off.
But which numbers have an odd number of divisors? Only perfect squares! For example, 9 has divisors 1, 3, 9. All other numbers have pairs of divisors. Therefore, only bulbs at perfect square positions remain on.
To solve the problem efficiently, we use the insight that only bulbs at perfect square positions are on at the end.
n
. This is the same as finding the largest integer k
such that k * k ≤ n
.
floor(sqrt(n))
.
Example Input: n = 10
Step-by-step:
import math
class Solution:
def bulbSwitch(self, n: int) -> int:
return int(math.isqrt(n))
class Solution {
public:
int bulbSwitch(int n) {
return (int)sqrt(n);
}
};
class Solution {
public int bulbSwitch(int n) {
return (int)Math.sqrt(n);
}
}
var bulbSwitch = function(n) {
return Math.floor(Math.sqrt(n));
};
The Bulb Switcher problem is a classic example of how mathematical insight can drastically simplify a problem. By recognizing that only bulbs at perfect square positions are toggled an odd number of times, we reduce the problem to counting perfect squares ≤ n
. This allows for a constant-time and space solution, making it both elegant and efficient.