subject
There are m taps in the pub for customers to pick up beer. Each tap produces the same amount of alcohol per second, which is 1. Existing n customers are ready to receive wine, and their initial order of reception has been determined. These customers are numbered from 1 to N in the order of receiving wine, and the quantity of receiving wine for customer I is w[i]. At the beginning of the reception, customers 1 to m each occupy a tap, and open the tap to receive the wine at the same time. When one of the customers J completed the requirement of w[j], the next customer k, who was waiting in line for the reception, immediately took over from the position of the customer J and began to pick up the wine. The process of changing people is instantaneous, and there is no waste of alcohol. That is to say, when J customer finishes picking up wine at the end of x second, k customer starts picking up wine at the end of x+1 second. If the current number of people receiving wine is less than m, there are only n taps for wine supply, while the other m-n taps are closed. Given the amount of alcohol received by n customers, according to the above rules, how many seconds does it take for all customers to finish drinking?
Title Analysis
For this problem, because n customers receive wine, we need to traverse the entire input array at least once, so the time complexity of the algorithm can not be less than O(n). Considering the total number of M faucets, there are also m individuals to receive wine. And the end of the earliest total is currently receiving the least amount of alcohol users need. That is to say, we need to find the earliest person at the end of each time. This can be achieved very easily with the smallest heap. Using the minimum heap to save the end time of the current recipient, we can decide which of the M current recipients ends first in O(1) time. At the same time, the minimum heap recovery time is O(logm). We just need to repeat this process, add the end time of the user to the minimum heap when the size is less than m, then take out the end time of the earliest user, get the end time as the current time, and add the next time of the queuing user to the heap on the basis of the current time, and put it into the heap, then the last time taken out of the heap is as follows The time it takes for a user to receive alcohol.
Spatiotemporal complexity
A minimum heap of m in size was used to store the users receiving the wine. Therefore, the spatial complexity is O(m).
All users are traversed, this is O(n). At the same time, each user is put into the heap and taken out of the heap once. After taking out, the heap is reopened to O(logm) and put into O(logm), so the time complexity is O(nlogm).
The algorithm is implemented as follows
public class GetBeerForAll {
public static int getBeer(int[] clients, int beerTap) {
// Deal with invalid inputs
if (clients == null || clients.length == 0 || beerTap == 0) {
return -1;
}
PriorityQueue<Integer> currClients = new PriorityQueue<>();
int index = 0; // the index of the next clients that will use the beer tap
int currTime = 0; // current time.
while (index < clients.length || !currClients.isEmpty()) {
// As long as the number of clients that is using beer tap right now is less
// than the total number of beer tap and there is more clients in line,
// we can put more clients into the PriorityQueue
// that contains the clients currently served by beer tap.
while(currClients.size() < beerTap && index < clients.length) {
currClients.add(clients[index++] + currTime);
}
// Otherwise, all clients is either already been served or is currently being served,
// constantly poll out the clients that finished the earliest and renew the current time
// until all clients finished.
// At this time, current time is the time that all clients have been served.
currTime = currClients.poll();
}
return currTime;
}
}