319. 灯泡开关

231 阅读2分钟

「这是我参与11月更文挑战的第13天,活动详情查看:2021最后一次更文挑战」。

题目

初始时有 n 个灯泡处于关闭状态。第一轮,你将会打开所有灯泡。接下来的第二轮,你将会每两个灯泡关闭一个。

第三轮,你每三个灯泡就切换一个灯泡的开关(即,打开变关闭,关闭变打开)。第 i 轮,你每 i 个灯泡就切换一个灯泡的开关。直到第 n 轮,你只需要切换最后一个灯泡的开关。

找出并返回 n 轮后有多少个亮着的灯泡。

截屏2021-11-15 下午10.50.51.png

思路分析

最简单的方式及时枚举,几个n就循环几次所有灯泡,时间复杂度是n^2,看了一眼官方提示:

提示:

  • 0 <= n <= 109

停止了这种不切实际的想法。

稍微画了前几种可能,发现新增一个数字并不会对之前的结果产生影响,换句话说可以将它类比为一个动态规划

if(满足了XX条件)dp[n + 1] = dp[n] + 1; else dp[n + 1] = dp[n];

由于这里只需要用到dp[n],因此根本不需要一个一维数组,直接用一个数存下来就好了。

这个条件就是因数,那么降低时间复杂度的方法找到了!只需要降低求因数的复杂度就可以了!赶紧去网上看看有什么现成的动态规划求因数个数的代码

桥豆麻袋!

然而关灯只有两种状态,像1 * n = n这类因数只会导致灯开了有关!真相只有一个,这个数字是不是完全平方数

int bulbSwitch(int n) {
        if (n == 0) return 0;
        if (n <= 3) return 1;
        int ret = 1;
        for(int i = 4; i <= n; i ++){
            // 判断一个元素的因数
            if((int)sqrt((double)i) * (int)sqrt((double)i) == i){
                ret++;
            }
        }
        return ret;
    }