前言
Bulb Switcher是LeetCode上的一道”脑筋急转弯”类题目,颇有趣味性。难度并不大,实际上想通数学规律后,此题只需要一行代码。
题目
https://leetcode.com/problems/bulb-switcher/
There are n bulbs that are initially off. You first turn on all the bulbs. Then, you turn off every second bulb. On the third round, you toggle every third bulb (turning on if it’s off or turning off if it’s on). For the ith round, you toggle every i bulb. For the nth round, you only toggle the last bulb. Find how many bulbs are on after n rounds.
Example:
Given n = 3.
At first, the three bulbs are [off, off, off].
After first round, the three bulbs are [on, on, on].
After second round, the three bulbs are [on, off, on].
After third round, the three bulbs are [on, off, off].So you should return 1, because there is only one bulb is on.
题意很清楚,就是第i次操作,把每i个灯泡中的最后一个转换一下状态。问最后还亮着的灯多少个。
分析
一开始做这个题,并没有想太多,就是手写了几个,找点规律。很容易就会发现——
0 : 0
1 - 3 : 1
4 - 8 : 2
9 - 15 : 3
16 - 24 :4
……
于是根据这样的规律,可以写出这样的代码:
class Solution {
public:
int bulbSwitch(int n) {
int i = 0;
for (; i*(i+2) < n; i++) {}
return i;
}
};
不过这样还是太繁琐了点,仔细想想,在所有操作中,被变换了奇数次状态的灯泡,会是亮着的。而被变换了偶数次状态的灯泡最后都灭了。又由于题目每次的操作是“转换每i个灯泡中的最后一个”,所以很明显是一道与因数分解有关的问题。
每个数字都有1和它本身这两个基本的因数,有多少个因数决定了这个数字所代表的位置的灯泡被转换多少次。观察下表:
1 ——— 1
2 ——— 1, 2
3 ——— 1, 3
4 ——— 1, 2, 4
5 ——— 1, 5
6 ——— 1, 2, 3, 6
7 ——— 1, 7
8 ——— 1, 2, 4, 8
9 ——— 1, 3, 9
我们发现,只有平方数的因子才是奇数个,那么这些位置的灯泡最后会亮着。所以我们只要根据给出的n得到不超过n的数字中有多少个平方数即可,而得到这个数字只需要计算n的平方根,舍弃小数部分即可。
代码
class Solution {
public:
int bulbSwitch(int n) {
return sqrt(n);
}
};