有LeetCode算法/华为OD考试扣扣交流群可加 948025485
可上全网独家的 欧弟OJ系统 练习华子OD、大厂真题
绿色聊天软件戳od1336
了解算法冲刺训练
视频地址:https://uha.xet.tech/s/JjALH
一、题目描述
初始时有 n
个灯泡处于关闭状态。第一轮,你将会打开所有灯泡。接下来的第二轮,你将会每两个灯泡关闭第二个。
第三轮,你每三个灯泡就切换第三个灯泡的开关(即,打开变关闭,关闭变打开)。第 i
轮,你每 i
个灯泡就切换第 i
个灯泡的开关。直到第 n
轮,你只需要切换最后一个灯泡的开关。
找出并返回 n
轮后有多少个亮着的灯泡。
示例 1:
输入:n = 3
输出:1
解释:
初始时, 灯泡状态 [关闭, 关闭, 关闭].
第一轮后, 灯泡状态 [开启, 开启, 开启].
第二轮后, 灯泡状态 [开启, 关闭, 开启].
第三轮后, 灯泡状态 [开启, 关闭, 关闭].
你应该返回 1,因为只有一个灯泡还亮着。
示例 2:
输入:n = 0
输出:0
示例 3:
输入:n = 1
输出:1
提示:
0 <= n <= 10^9
二、题目解析
数学归纳法严格证明
假设结论“当灯泡数目为n-1
时,经过n-1
轮后,最后有剩下floor(sqrt(n-1))
个灯泡是亮着的”成立,用数学归纳法证明,需要考虑
- 灯泡数目为
n = 1
的情况 - 灯泡数目为
n
的情况
n = 1
时,第1
个灯泡经过1
轮后从关变到开,上述结论显然成立。故证明的重点是,考虑灯泡数目取n
时,结论“当灯泡数目为n
时,经过n
轮后,最后有剩下floor(sqrt(n))
个灯泡是亮着的”是否成立。
当灯泡数目为n
时,考虑前n-1
个灯泡的行为:
- 经过
n-1
轮后,前n-1
个灯泡的行为和考虑灯泡数目为n-1
时经过n-1
轮后的行为是完全一致的,故此时有floor(sqrt(n-1))
个灯泡是亮着的。 - 在第
n
轮中,只有第n
个灯泡进行了切换,故前n-1
个灯泡会维持存在floor(sqrt(n-1))
个灯泡是亮着的情况。
考虑最后一个灯泡,即第n
个灯泡在n
轮中的行为。
注意到,当且仅当i
是n
的因数时,第n
个灯泡在遇到第i
轮的时候会切换状态。考虑n
的因数个数
- 若个数为偶数,那么经过偶数次状态转换后,第
n
个灯泡的状态为关。 - 若个数为奇数,那么经过奇数次状态转换后,第
n
个灯泡的状态为开。
因数总是成对出现的,假设i
为n
的因数,那么n/i
一定是n
的因数。即灯泡会在第i
轮和第n/i
轮,都会进行状态切换。
- 若
i != n/i
,那么会进行2
次切换。 - 若
i == n/i
,那么仅进行1
次切换,即第i
轮和第n/i
轮属于同一轮。
根据i == n/i
可以计算出,i^2 == n
。我们可以得出结论:当且仅当n
为某个正整数i
的平方,即当n
为一个完全平方数时,第n
个灯泡经过n
轮会经过奇数次状态转换,最终的状态为开。
令A
和B
是满足A^2 <= n-1 <= B^2
和A+1 = B
成立的两个正整数,即n-1
是位于两个相差为1
的正整数A
和B
的平方A^2
和B^2
之间的一个整数。显然A = floor(sqrt(n-1))
。
我们将考虑前n-1
个灯泡和第n
个灯泡的情况结合起来,计算经过n
轮之后状态为开的灯泡的总数。若
n
不是完全平方数- 那么
n
的最终状态为关,最终亮着的灯泡数为前n-1
个灯泡亮着的数目,即floor(sqrt(n-1))
。 - 由于
n
不是完全平方数,那么A^2 <= n-1 < n < B^2
成立,此时存在A = floor(sqrt(n))
成立,故floor(sqrt(n-1)) = floor(sqrt(n))
成立。 - 因此,对于
n
个灯泡经过n
轮,最终会有floor(sqrt(n))
个灯泡亮着,结论成立。
- 那么
n
是完全平方数- 那么
n
的最终状态为开,最终亮着的灯泡数为前n-1
个灯泡亮着的数目加上第n
个灯泡,即floor(sqrt(n-1))+1
。 - 由于
n
是完全平方数,那么A^2 <= n-1 < n = B^2
成立,此时存在B = floor(sqrt(n))
成立,故floor(sqrt(n-1))+1 = A+1 = B = floor(sqrt(n))
成立。 - 因此,对于
n
个灯泡经过n
轮,最终会有floor(sqrt(n))
个灯泡亮着,结论成立。
- 那么
综合上述两种情况,数学归纳法得证,结论“当灯泡数目为n
时,经过n
轮后,最后有剩下floor(sqrt(n))
个灯泡是亮着的”成立。
三、参考代码
1、Java 代码
// 登录 AlgoMooc 官网获取更多算法图解
// https://www.algomooc.com
// 作者:程序员吴师兄
// 添加微信 278166530 获取最新课程
// 代码有看不懂的地方一定要私聊咨询吴师兄呀
// 灯泡开关(LeetCode 319):https://leetcode.cn/problems/bulb-switcher/
class Solution {
public int bulbSwitch(int n) {
// n = 14 , 3.xx
// n = 15 , 3.xx
// n = 16 , 4
// 求小于等于 n 的完全平方数的个数
return (int)Math.sqrt(n);
}
}
2、C++代码
class Solution {
public:
int bulbSwitch(int n) {
return sqrt(n + 0.5);
}
};
3、Python 代码
class Solution:
def bulbSwitch(self, n: int) -> int:
return int(sqrt(n + 0.5))
华为OD算法/大厂面试高频题算法练习冲刺训练
-
华为OD算法/大厂面试高频题算法冲刺训练目前开始常态化报名!目前已服务300+同学成功上岸!
-
课程讲师为全网50w+粉丝编程博主@吴师兄学算法 以及小红书头部编程博主@闭着眼睛学数理化
-
每期人数维持在20人内,保证能够最大限度地满足到每一个同学的需求,达到和1v1同样的学习效果!
-
60+天陪伴式学习,40+直播课时,300+动画图解视频,300+LeetCode经典题,200+华为OD真题/大厂真题,还有简历修改、模拟面试、专属HR对接将为你解锁
-
可上全网独家的欧弟OJ系统练习华子OD、大厂真题
-
可查看链接 大厂真题汇总 & OD真题汇总(持续更新)
-
绿色聊天软件戳
od1336
了解更多