简体   繁体   中英

return the number of times is state of bulb changed?

Today in an exam I faced a problem which is Toggled Switches(Hacker Earth) as it is an exam question So, I am unable to send the question or its link (exactly).

Problem: we have to print a number representing the number of times do bulb changed its state. The bulb is attached to the "n" number of switches. So the bulb will be in the "on" state only when half or more than half of the given n of switches to be "on".

1 represents on state

0 for off respectively.

There is also a query that will be given to represent which switch has to be toggled ( change from on to off or vice-versa 1 ->0 or 0->1). So, by toggling may or may not the bulb state change. so we have to return the number of times it changed its state.

input:

1 - number of test case

3 - number of switches (n)

1 1 0 - initial all n switches states

3 - number of switches to be toggled

3 2 1 -> (3 represents third switch ie as index wise second in switches array.) switches that have to be toggled.

output:

1 - number of times the bulb changed its state.

explanation : initial array or switches state [1, 1, 0] as half or more than half switches are in on. hence bulb is in on state. as per queries [3,2,1]

we have to toggle the 3 rd switch. As initially third is in off [1,1,0] after toggling it changes to on [1,1,1] present switches state. as all are in on position bulb is on. ( no changes in the state of the bulb)

Now, have to toggle 2 nd switch so [1,1,1] changes to [1,0,1] switches states as half switches are on the bulb is on. ( no changes in the state of the bulb)

Now, 1 st switch to be toggled. Hence [1,0,1] changes to [0,0,1]. as not equal or more than half switches are in on states hence bulb is going to be off. ( now bulb state is changed)

Hence the output is one.

I wrote the answer to this I am only able to solve the sample test case. No hidden test case is got the right answer and some got time exceeds error. so totally 0 marks.

I am a beginner so please explain vividly where I am wrong what is wrong? how it can be efficient?.

and my code is

    import java.util.*;
    public class Main{
        static Scanner scan = new Scanner(System.in);
        public static void main(String[] args) {
        int test_cases = scan.nextInt();
    while(test_cases>0){
        //number of switches
        int n  = scan.nextInt();
        // contains on / off positions of switches
        int [] switches = new int[n];
        for(int i =0;i<n;i++)
        switches[i]=scan.nextInt();
        //number of queries 
        int q = scan.nextInt();
        //  starts at 1 i.e queries[0]=1 but represents switch index 1(queries representing switch position and tha position starts from 1)
        int [] queries  = new int[q];
        for(int i =0;i<q;i++)
        queries[i]=scan.nextInt();
        int result  = toggled(n,switches,q,queries);
        System.out.println(result);
        test_cases--;
    }
    }
    static int toggled(int n,int switches[],int q,int queries[]){
        if(n==1)
        return q;
        int result =0;
        //giving switch state on or off
        boolean initial = on(switches);
        //System.out.println("initial is "+initial);
        //to represent on or off for all toggle including initial
        boolean [] states = new boolean[q+1];
        states[0] = initial;
        int count  = 0;
        //to represent index of states
        int state_count =1;
        while(count<q){
            if((switches[queries[count]-1] & 1 )== 1)
            switches[queries[count]-1] = 0;
            else
            switches[queries[count]-1] = 1;
     
     states[state_count++]=on(switches);
     count++;
        }
       //System.out.println("state_count is "+state_count);
       for(int i =1;i<state_count;i++){
           if(initial ^ states[i] )
           {
               result+=1;
               initial = states[i];
           }
       }
       return result;
    }
    //method to evaluate whether to consider on or off ( to on(bulb) have to on atleast half of the switches)
    static boolean on(int arr[]){
        int sum = 0;
        for(int i =0;i<arr.length;i++)
            sum+=arr[i];
        
        if(sum>=arr.length/2.0)
            return true;
            else 
            return false;
            
        
    }
}

It seems like your on() function is taking n (linear) time where n is the number of switches. Total time complexity would be O(n*q) q is a number of queries. You can bring it down to O(n+q) .

I am not familiar with Java therefore Python

Text after # denotes a comment in Python

def on(number_of_on, n) : # //takes O(1)
    '''// Returns 1 if more than half or half of the switches are ON else returns 0'''
    if (number_of_on >= n/2) :
        return 1 #// ON STATE
    else :
        return 0 #// OFF state

for t in range(int(input())) : #// test cases (1)
    n = int(input()) #// number of switches (3)
    switches = list(map(int, input().split())) #// initial state of switches(1 1 0)
    q = int(input()) #// number of queries (3)
    queries = list(map(int, input().split())) #// toggle sequence (3 2 1)

    number_of_on = 0 #// denote number of bulbs which are ON
    count = 0 #// number of changes (ANSWER)
    
    for i in range(n) : #// O(n)
        if switches[i] == 1 :
            number_of_on += 1
          
    current = on(number_of_on, n) #// FUNCTION CALL
          
    for i in range(q) : #// ITERATING IN QUERIES
        if switches[queries[i]-1] == 1 : #//  IF switch at 'q' is 1 (ON)  
            switches[queries[i]-1] = 0 #// TURNING it OFF
            number_of_on -= 1 #// number of OFF will be (-1)
            if on(number_of_on, n) == False and current == 1 : #// if on() returns False/0 (OFF) AND current is ON/1
                current = 0 #// change current state
                count += 1 #// count++ (change in state)
        else :
            switches[queries[i]-1] = 1 
            number_of_on += 1
            if on(number_of_on, n) == True and current == 0 : #// if on() returns TRUE/1 (ON) AND current is OFF/0
                current = 1 #// change current state
                count += 1 #// count++ (change in state)
    print(count) #// ANSWER

Function on(number_of_on, number_of_switches) // Returns 1 if more than half or half of the switches are ON else returns 0

  • n // number of switches (3) - input
  • switches // initial state of switches(1 1 0) - input
  • q // number of queries (3) - input
  • queries // toggle sequence (3 2 1) - input
  • number_of_on = 0 // denote number of bulbs which are ON
  • count = 0 // number of changes (ANSWER)
  1. Firstly counting the number of switches that are ON and will store them in the variable number_of_on will take O(n) time.

  2. and see the current state of the bulb by calling a function on(number_of_on, number_of_switches) and assign value to the current variable.

  3. Then iterate over the queries (i - for loop variable)

  • if the value at element at index queries[i]-1 is 1, means we will toggle OFF the switch and decrease the value of number_of_switches by 1. number_of_swiches -= 1; now we will call the function on(number_of_on, number_of_switches) and if the value return is 1 and the current was 0 means the bulb must have changed its state (from 0 -> 1). SO count += 1

  • if the value at element at index queries[i]-1 is 0, means we will toggle ON the switch and increase the value of number_of_switches by 1. number_of_swiches += 1; now we will call the function on(number_of_on, number_of_switches) and if the value return is 0 and the current was 1 means the bulb must have changed it state (from 1 -> 0). So count += 1 .

I tested your code. I found one logical error in the method I mention below.

static boolean on(int arr[])
{
     int sum = 0;
     
     for(int i = 0;i < arr.length;i++) sum+=arr[i];
   
     //The test expression should be sum >= arr.length/2.0
     if(sum > arr.length/2.0) return true;
     else return false;

You said in the problem statement:

So the bulb will be in the "on" state only when half or more than half of the given n of switches to be "on".

To test this condition the test expression should be

if (sum >= arr.length/2.0)

and not

if (sum > arr.length/2.0)

Another improvement in your code is its time complexity . Currently you are checking the state of the bulb by checking all the switches.

There are n number of bulbs and q number of queries . If you check the state of the bulb in this manner it will result in O(q*n) .

It can be done in O(q + n) .

Logic in Brief:

If you declare a variable to store the total number of switches on and update it after each query. Then use this variable to check if there is a change in the state of the bulb, your code will be more efficient.

I have provided a code below using this implementation.

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));

    int testCases = Integer.parseInt(bufferedReader.readLine().trim());
    //To score output of all the testCases
    int[] result = new int[testCases];

    for (int i = 0;i < testCases;i++)
    {
        //number of bulbs
        int n = Integer.parseInt(bufferedReader.readLine().trim());
        //input in String array
        String[] in = bufferedReader.readLine().split(" ");
        //To count how many switches are in on state
        int countOn = 0;
        //To store if the bulb is currently on or not
        boolean isBulbOn;

        //Converting the input String array to number array
        int[] bulbState = new int[n];
        for(int j = 0;j < n;j++)
        {
            int x = Integer.parseInt(in[j]);
            bulbState[j] = x;

            if (x == 1) countOn++;
        }
        //Initializing isBulbOn to true if countOn >= n/2
        //Math.ceil() conversion is necessary since in case of odd number of bulbs n/2 will result in 1
        //and isBulbOn condition will be assigned an incorrect value
        //Here 2.0 is necessary since if it just to n/2 will result in integer not a double
        isBulbOn = countOn >= (int)Math.ceil(n/2.0);

        //Input number of queries and store it
        int q = Integer.parseInt(bufferedReader.readLine().trim());
        String[] toggleInput = bufferedReader.readLine().trim().split(" ");

        //To count number of times the state has changed
        int countStateChange = 0;

        for (int j = 0;j < q;j++)
        {
            int currentToggle = Integer.parseInt(toggleInput[j]);

            //If switch is on make it off else do the opposite
            if(bulbState[currentToggle-1] == 0)
            {
                bulbState[currentToggle-1] = 1;
                countOn++;
            }
            else
            {
                bulbState[currentToggle-1] = 0;
                countOn--;
            }

            //Check if bulb was previously on and the switch on is less than half of n
            //Register a state change
            if (isBulbOn && countOn < (int)Math.ceil(n/2.0))
            {
                isBulbOn = false;
                countStateChange++;
            }

            //Check if bulb was previously off and the switch on is more than or equal to half of n
            //Register a state change
            if (!isBulbOn && countOn >= (int)Math.ceil(n/2.0))
            {
                isBulbOn = true;
                countStateChange++;
            }
        }

        //store the result of current test case
        result[i] = countStateChange;
    }

    //Print all the results
    for (int x: result)
        System.out.println(x);
}

I hope I have helped you. I did test my code against various inputs. Do comment if you find any problems or if any part of my code is hard to understand.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM