leetcode319 Bulb Switcher

1.问题描述

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 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.

有 n 盏电灯,最开始时都是关着的。现在要进行 n 轮操作:
第1轮操作是把每一盏灯的开关按一下(全部打开)。
第2轮操作是把每两盏灯的开关按一下,即第2,4,6,8…盏灯的开关按一下。
第3轮操作是把每三盏灯的开关按一下,即第3,6,9…盏灯的开关按一下。
如此往复,直到第 n 轮,即只按一下第 n 盏灯的开关。
现在给你输入一个正整数 n 代表电灯的个数,问你经过 n 轮操作后,这些电灯有多少盏是亮的?

2.暴力解法

    private static int buldSwitchForce(int n) {
        boolean[] flags = new boolean[n];
        for(int i=1; i<=n; i++) {
            for(int j=1; j<=n; j++) {
                if (i%j == 0) {
                    flags[i-1] = flags[i-1] == true ? false: true;
                }
            }
        }
        int count = 0;
        for(boolean each: flags) {
            if (each) count += 1;
        }
        return count;
    }

暴力解法就是两层循环:
第一层循环表示第几盏灯,等的状态用布尔数组描述,如果false表示关,如果true表示打开。
第二层循环表示第k轮循环,如果i%j==0,表示这盏灯的状态要发生改变。如果这盏灯之前的状态是开的(true),那么要变成关(false)的状态,反之亦然。
最后计算数组中状态为true的个数,就是灯还亮的个数。
这种算法的时间复杂度 O ( n 2 ) O(n^2) O(n2)

3.更好的解法

上面的暴力解法,肯定不是我们希望的最优解,下面来分析一下更好的解法。
对于这种一开始没有太多头绪的情况,我们可以采用常见的递推,或者说找规律的方法来试试
假设n=3,最终结果为1,只有第一盏灯最后亮。
第一轮的时候,所有灯都被打开。
第二轮的时候,第二盏灯被灭了。
第三轮的时候,第三盏灯被灭了。
2 = 2 ∗ 1 , 3 = 3 ∗ 1 2=2*1, 3=3*1 2=21,3=31
假设n=4,最终结果为2,有两盏灯最后亮。
第一轮的时候,所有灯都被打开。
第二轮的时候,第二盏灯,四盏灯被灭了。
第三轮的时候,第三盏灯被灭了。
第四轮的时候,第四盏灯被灭了。
2 = 2 ∗ 1 , 3 = ∗ 1 , 4 = 4 ∗ 1 = 2 ∗ 2 2=2*1, 3=*1, 4=4*1=2*2 2=21,3=1,4=41=22
如果我们从n一直取到8,最终结果都是2。到9的时候,最终结果就变成了3。因为 9 = 1 ∗ 9 = 3 ∗ 3 9=1*9=3*3 9=19=33

一个灯从初始时的灭,到最后第n轮结束,要经历多次状态的切换,如果经历了奇数次,则最后是亮的,否则是灭的。根据上面的推导不难看出,一个数为完全平方数,其不重复因数个数才为奇数个。因为如果不为完全平方数,肯定可以表示为成对因数的乘积。

所以最后的结果可以表示为:

    private static int bulbSwitch(int n)  {
        return (int)Math.sqrt(n);
    }

为什么求平方根就可以?
假设我们现在有9盏灯,最后结果为3,亮着的三盏灯就是 1 = 1 ∗ 1 , 4 = 2 ∗ 2 , 9 = 3 ∗ 3 1=1*1, 4=2*2, 9=3*3 1=11,4=22,9=33这三盏,所以直接取平方根即可。

猜你喜欢

转载自blog.csdn.net/bitcarmanlee/article/details/114025533