题目描述
初始时有 n 个灯泡关闭。 第 1 轮,你打开所有的灯泡。 第 2 轮,每两个灯泡你关闭一次。 第 3 轮,每三个灯泡切换一次开关(如果关闭则开启,如果开启则关闭)。第 i 轮,每 i 个灯泡切换一次开关。 对于第 n 轮,你只切换最后一个灯泡的开关。 找出 n 轮后有多少个亮着的灯泡。
示例:
输入: 3
输出: 1
解释:
初始时, 灯泡状态 [关闭, 关闭, 关闭].
第一轮后, 灯泡状态 [开启, 开启, 开启].
第二轮后, 灯泡状态 [开启, 关闭, 开启].
第三轮后, 灯泡状态 [开启, 关闭, 关闭].
你应该返回 1,因为只有一个灯泡还亮着。
来源:LeetCode
思路
此题主要考察的是思想,而非编码能力,找到方法,代码很简单。
我们分几步来考虑:
- 对于单个灯泡来看,第 i 个灯泡只可能在第 1 到 i 次被切换。那它最终亮还是灭只要看它被切换奇数次还是偶数次。
- 第 i 个灯泡只有在第 j 次操作时才会被切换,其中 i%j 为 0,即 j 为 i 的
因子。i 的因子的个数就是被切换的次数。 - i 的因子个数是奇数还是偶数,要看 i 是否为
平方数,i 的平方根是一个单独的因子,其他的因子必然是成对出现。比如 16,它的因子 1 和 16,2 和 8,都是成对出现,而平方根 4 是单独一个。
- 那么 1 到 n 中平方数的个数,即是最终亮着灯泡的个数。
- 设 k 为 √n 的向下取整,则小于 n 的平方数的根必然依次落在 1~k 之间。所以 k 即是 1~n 中的平方数个数。
解法
/**
* @param {number} n
* @return {number}
*/
const bulbSwitch = n => ~~Math.sqrt(n);