319. Bulb Switcher

Problem statement:

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 ith round, you toggle every i bulb. 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.

Analysis:

For the solution, it is the most simple answer in leetcode I have ever seen, return sqrt(n), orz. But it is hard to figure it out.

I can tell my story about how to solve this problem. Although is not smart as those top rated, I like this track to solve the problem.

Solution one: TLE

It literally translates what is described in the problem. There are n rounds, and we turn on and off the corresponding lights.

The time complexity of outer layer is O(n).

The time complexity of inner layer is 1/2 + 1/3 + 1/4 + ... , it is O(n). 

The total time complexity is O(n * n). For this question, there is no doubt to be declined. TLE!!!

class Solution {
public:
    int bulbSwitch(int n) {
        vector<int> lights(n, 1);
        int cnt = n;
        for(int i = 1; i < n; i++){
            int gap = i;
            for(int j = gap ; j < n; j += gap + 1){
                if(lights[j] == 1){
                    lights[j] = 0;
                    cnt--;
                } else {
                    lights[j] = 1;
                    cnt++;
                }
            }
            gap++;
        }
        return cnt;
    }
};

Solution two: TLE

Since I am declined by the system, so optimize it. How?

Think deeply, I found that the lights are on only if it is switched odd times. For a number, it has to have odd common divisor. I know how to find the number of common divisor for a given number in O(n ^1/2). Adding the traverse complexity, the total time complexity is O(n ^ 3/2). It is also declined.

class Solution {
public:
    int bulbSwitch(int n) {
        int lights_cnt = 0;
        for(int i = 1; i <= n; i++){
            if(common_divisor_count(i) % 2){
                lights_cnt++;
            }
        }
        return lights_cnt;
    }
private:
    int common_divisor_count(int n){
        int cnt = 0;
        for(int i = 1; i * i <= n; i++){
            if(n % i == 0){
                cnt++;
                if(n / i != i){
                    cnt++;
                }
            }
        }
        return cnt;
    }    
};

Solution three: math (AC)

From leetcode discussion, smart brains delivered the most brilliant solutions.

For a given number, only those who is a square of a number have odd common divisor. It is obvious from my code of solution two. 

That means the number of lights on, equals to how many square numbers from 1 to n.

Just return sqrt(n).

Summary:

Since Leetcode only accepts the most brilliant solutions, but I like to think of a computer philosophy. For this problem, it is pure math. I am not that smart guys, can not return the answer by a function call. We should applaud for the smart solutions. But I think it is still valuable to find an approach to optimize the solution step by step.

原文地址:https://www.cnblogs.com/wdw828/p/6865835.html