「这是我参与11月更文挑战的第13天,活动详情查看:2021最后一次更文挑战」。
题目
初始时有 n 个灯泡处于关闭状态。第一轮,你将会打开所有灯泡。接下来的第二轮,你将会每两个灯泡关闭一个。
第三轮,你每三个灯泡就切换一个灯泡的开关(即,打开变关闭,关闭变打开)。第 i 轮,你每 i 个灯泡就切换一个灯泡的开关。直到第 n 轮,你只需要切换最后一个灯泡的开关。
找出并返回 n 轮后有多少个亮着的灯泡。
思路分析
最简单的方式及时枚举,几个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;
}