• [LeetCode] Bulb Switcher


    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 i-th round, you toggle every i bulb. For the n-th round, you only toggle the last bulb. Find how many bulbs are on after n rounds.

    Example:

    Input: 3
    Output: 1 
    Explanation: 
    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次循环,第i次循环就将第1*i、2*i、3*i...个灯泡转换状态。求n次之后,有多少个灯泡状态为开。

    还是先枚举个小例子来分析下,比如只有5个灯泡的情况,'X'表示亮,‘√’表示灭,如下所示:

    初始状态:    X    X    X    X    X

    第一次:      √    √    √    √    √

    第二次:      √     X    √    X    √

    第三次:      √     X    X    X    √

    第四次:      √     X    X    √    √

    第五次:      √     X    X    √    X


    方法1:根据题意分析,很容易想到用两个循环来做,外循环用来循环次数,内循环用来改变灯泡的状态。这里用0表示关,1表示开。代码如下:

     1     public int bulbSwitch(int n) {
     2         int[] bulbs = new int[n];
     3         for ( int i = 0 ; i < n; i ++ ){
     4             for ( int j = i ; j < n ; j=j+i+1 )
     5                 bulbs[j] = bulbs[j]==1?0:1;
     6         }
     7         int sum = 0;
     8         for ( int i : bulbs ) sum+=i;
     9         return sum;
    10     }

    思路和代码是正确的,但是时间复杂度太高,提交之后显示超时了,因此换了其他的解法。


    方法2:参考@Grandyang的解题思路,整理如下:研究一下灯泡状态变化的规律,发现对于第n个灯泡,当次数是n的因子的时候,状态会改变,也就是n可以被i整除的时候改变状态。例如当n=36时,因子对有(1,36)(2,18)(3,12)(4,9)(6,6)。对于(1,36),第1次循环改变之后第36次循环又改变回来了,所以这个因子对实际对状态并没有发生改变,还是关状态。只有(6,6)这个因子本质上改变了灯泡的状态。因此我们只要寻找<=n的完全平方数就可以了。这里可以用暴力方法来寻找,代码如下:

    1     public int bulbSwitch(int n) {
    2         int res = 1;
    3         while ( res * res <= n ) res++;
    4         return res-1;
    5     }

    提交成功,时间为1ms,已经时很数学的方法了。


    方法3:还有一种更简单的方法,直接对n求开方,得到的数就是n以内的完全平方数。刚开始还挺难理解的,被同学一句话点醒,因为比sqrt(n)小的整数i,其i^2一定小于n,所以直接返回sqrt(n)就可以了。代码就不放上去了,估计0ms。

    总结一下,数学真美。

  • 相关阅读:
    web常用自动化库——selenium总结
    python协程总结
    python多进程总结
    python多线程总结
    Scrapy进阶知识点总结(六)——中间件详解
    Git用法总结
    Scrapy进阶知识点总结(五)——Settings
    Scrapy进阶知识点总结(四)——Item Pipeline
    Scrapy进阶知识点总结(三)——Items与Item Loaders
    Scrapy进阶知识点总结(二)——选择器Selectors
  • 原文地址:https://www.cnblogs.com/boris1221/p/9259714.html
Copyright © 2020-2023  润新知