LeetCode/solutions/319. Bulb Switcher.md
2019-11-16 17:51:50 +08:00

2.0 KiB
Raw Blame History

319. Bulb Switcher

思路

有n个初始全灭的灯泡第一次更改所有灯泡的状态即全部打开第二次更改2、4...灯泡的状态第三次更改第3、6...灯泡的状态以此类推第n次更改第n个更改灯泡的状态。然我们求最后亮灯泡的个数。

由题意可知,某个灯泡最后的状态取决于它被更改了多少次,如果被更改了偶数次那么就回到初始灭态,若被更改了奇数次就是亮态。 那么第i个灯泡被更改了多少次呢由题意分析可知被更改了dp[i]次dp[i]代表i的所有因数个数。那如何求1-n共n个数的各自的因数个数呢 我们知道,若m*n = k那么m和n都是k的因数注意考虑m是否等于n所以我们可以写一个二重循环来不断更新dp

for i in [1, sqrt(n)]:
  for j in [i, n/i]:
      dp[i*j] += (i == j ? 1:2)

因此最后的完整代码就为:

class Solution {
public:
    int bulbSwitch(int n) {
        vector<int>dp(n+1, 0);
        int res = 0;
        for(int i = 1; i <= int(sqrt(n)); i++){
            for(int j = i; j <= n / i; j++)
                dp[j*i] += (i == j ? 1:2);
            
            res += (dp[i] % 2);
        }
        
        return res;
    }
};

稍加分析上述代码可以发现:在第二重循环中若i != j时会增加两个因数但是我们最后会对因数对2取模也就是说其实是不用考虑i != j情况的, 则循环代码就变成

for(int i = 1; i <= int(sqrt(n)); i++){
    dp[i*i] += 1;
    res += (dp[i*i] % 2); // 即 res += 1
}

直观上也很好理解若k不是平方数对于任意k的因数m一定能找到唯一的n = k/m也是k的因数其中m != n因此k的因数个数一定是偶数。

也就是说求1-n有多少个平方数那我们直接返回sqrt(n)就可以了,所以最后的代码很简单,如下。

C++

class Solution {
public:
    int bulbSwitch(int n) {
        return sqrt(n);
    }
};