Tuesday, August 29th

 Shop penalties

Given a customer log consisting of 'Y's and 'N's, find the hour of the minimum penalty.  A penalty occurs when a no customer is in store while it's open, or closed when a customer arrives. Arrival times are denoted by index in the customer array.


This problem can be solved using brute force.  Iterate over every index in the customer array, and for each index, iterate over the values before and then after the index, calculating the penalties, then taking the minimum.  The runtime for this is O(n^2), so while it may work, it times out for larger inputs.

This can be improved upon.  The idea is to calculate the penalty for the first hour, then iterate over the customer array and recalculate the penalty for each hour.  

Initialize some variables

    int bestClosingTime(string customers) {
        int n=customers.size(); //number of customers
        int numn=0, numy=0; //number of 'Y's and 'N's in the customer array
        int pen; //the current penalty 
        int minpen=INT_MAX, minhour; //minimum penalty and the hour it occurs
        ...
    }      

Then iterate over the customer array once, and count the number of 'Y's and 'N's.  For the first hour, the penalty is equal to the number of 'Y's

    for(int i=0; i<n; i++) {
if(customers[i]=='Y') numy++;
else numn++;
}
int pen=numy;

Now iterate over the customer array for the second time.  This time, first test if the current penalty pen is less than the minimum penalty, and if so, update the minimum penalty and the hour i.  Then, if the character is equal to 'Y', reduce the current penalty by 1, else the character is an 'N' so increment the penalty.

    for(int i=0; i<n; i++){
if(pen<minpen) {
minpen=pen;
minhour=i;
}
if(customers[i]=='Y') pen--;
else pen++;
}

Then, outside the for loop, test the condition where hour is equal to customer array size 'n', meaning all 'N's come before the latest possible closing time.  If the number of 'N's is less than the minimum penalty, update it.

if(numn<minpen) {
minpen=numn;
minhour=n;
}

Finally, return the minimum hour

return minhour;

Full code below:

    int bestClosingTime(string customers) {
int n=customers.size();
int numn=0, numy=0;
for(int i=0; i<n; i++) {
if(customers[i]=='Y') numy++;
else numn++;
}
int pen=numy;
int minpen=INT_MAX, minhour;
for(int i=0; i<n; i++){
if(pen<minpen) {
minpen=pen;
minhour=i;
}
if(customers[i]=='Y') pen--;
else pen++;
}
if(numn<minpen) {
minpen=numn;
minhour=n;
}
return minhour;
}

This idea can be improved upon.  Instead of 2 passes, it a solution can be reached in 1 pass.  The problem only asks for the hour of the minimum penalty, not the penalty itself.  All the penalties become relative.  So the first pass used to calculate the number of 'Y's can be left out.  The initial penalty can be 0 and then is recalculated by iterating over the customer array in the same manner as before.


Comments

Popular posts from this blog

Wednesday, September 20th

Monday, September 11th

Tuesday, September 19th