Design Underground System
An underground railway system is keeping track of customer travel times between different stations. They are using this data to calculate the average time it takes to travel from one station to another.
Implement the UndergroundSystem
-
void checkIn(int id, string stationName, int t) -
A customer with a card ID equal to
, checks in at the stationid at timestationName .t - A customer can only be checked into one place at a time.
-
void checkOut(int id, string stationName, int t) -
A customer with a card ID equal to
, checks out from the stationid at timestationName .t -
double getAverageTime(string startStation, string endStation) -
Returns the average time it takes to travel from
tostartStation .endStation -
The average time is computed from all the previous traveling times from
tostartStation that happened directly, meaning a check in atendStation followed by a check out fromstartStation .endStation -
The time it takes to travel from
tostartStation may be different from the time it takes to travel fromendStation toendStation .startStation -
There will be at least one customer that has traveled from
tostartStation beforeendStation is called.getAverageTime
You may assume all calls to the checkIncheckOutt1t2t1 < t2
Example 1
"checkIn" : [45,"Leyton",3]
"checkIn" : [32,"Paradise",8]
"checkIn" : [27,"Leyton",10]
"checkOut" : [45,"Waterloo",15]
"checkOut" : [27,"Waterloo",20]
"checkOut" : [32,"Cambridge",22]
"getAverageTime" : ["Paradise","Cambridge"]
"getAverageTime" : ["Leyton","Waterloo"]
"checkIn" : [10,"Leyton",24]
"getAverageTime" : ["Leyton","Waterloo"]
"checkOut" : [10,"Waterloo",38]
"getAverageTime" : ["Leyton","Waterloo"]
Output:
Operation 1 "checkIn" : void
Operation 2 "checkIn" : void
Operation 3 "checkIn" : void
Operation 4 "checkOut" : void
Operation 5 "checkOut" : void
Operation 6 "checkOut" : void
Operation 7 "getAverageTime" : 14.00000
Operation 8 "getAverageTime" : 11.00000
Operation 9 "checkIn" : void
Operation 10 "getAverageTime" : 11.00000
Operation 11 "checkOut" : void
Operation 12 "getAverageTime" : 12.00000
Explanation:
undergroundSystem.checkIn(45, "Leyton", 3);
undergroundSystem.checkIn(32, "Paradise", 8);
undergroundSystem.checkIn(27, "Leyton", 10);
undergroundSystem.checkOut(45, "Waterloo", 15); // Customer 45 "Leyton" -> "Waterloo" in 15-3 = 12
undergroundSystem.checkOut(27, "Waterloo", 20); // Customer 27 "Leyton" -> "Waterloo" in 20-10 = 10
undergroundSystem.checkOut(32, "Cambridge", 22); // Customer 32 "Paradise" -> "Cambridge" in 22-8 = 14
undergroundSystem.getAverageTime("Paradise", "Cambridge"); // return 14.00000. One trip "Paradise" -> "Cambridge", (14) / 1 = 14
undergroundSystem.getAverageTime("Leyton", "Waterloo"); // return 11.00000. Two trips "Leyton" -> "Waterloo", (10 + 12) / 2 = 11
undergroundSystem.checkIn(10, "Leyton", 24);
undergroundSystem.getAverageTime("Leyton", "Waterloo"); // return 11.00000
undergroundSystem.checkOut(10, "Waterloo", 38); // Customer 10 "Leyton" -> "Waterloo" in 38-24 = 14
undergroundSystem.getAverageTime("Leyton", "Waterloo"); // return 12.00000. Three trips "Leyton" -> "Waterloo", (10 + 12 + 14) / 3 = 12
Constraints:
1 <= id, t <= 106- 1 <= stationName.length, startStation.length, endStation.length <= 10
- All strings consist of uppercase and lowercase English letters and digits.
- There will be at most
calls in total to2 * 104 ,checkIn , andcheckOut .getAverageTime - Answers within
of the actual value will be accepted.10-5
Solution 1 - Store checkin and checkout time information into a HashMaps
In this approach, we will use two HashMap
Implementation steps:
-
We will create two
's,HashMap to store checkin information, andcheckInMap to track total time took between stations, and the number of travels made between those stations, that reason we track this is to compute the average,totalTimeToCountMap .average = total time / count -
Implementation steps for
:checkIn (id, stationName, t)-
In
method, add this information intocheckIn , withcheckInMap as key andid pair as value.(stationName, t)
-
In
-
Implementation steps for
:checkOut (id, stationName, t)-
When a person is checked out, we will get their checkin information from
using the theircheckInMap , and then get the total time it took from starting station to end station by taking the diff betweenid passed tot method and thecheckOut stored int . We then store information intocheckinMap withtotalTimeToCountMap pair as key and(startStation, endStation) pair as value.(total time it took to travel, number of travels made between these stations)
-
When a person is checked out, we will get their checkin information from
-
Implementation steps for
:getAverageTime(String startStation, String endStation)-
We will get total time and count information from
by passingtotalTimeToCountMap as key and simply compute(startStation, endStation) /total time it took to travel that is already stored as value in the map.number of travels made between these stations
-
We will get total time and count information from
import java.util.AbstractMap.SimpleEntry;
import java.util.HashMap;
public class UndergroundSystem {
HashMap<Integer, SimpleEntry<String, Integer>> checkInMap = new HashMap<>(); // Id -> (stationName, t)
HashMap<SimpleEntry<String, String>, int[]> totalTimeToCountMap = new HashMap<>(); //(startStation, endStation)
// -> (totalTime, count)
public UndergroundSystem() {}
public void checkIn(int id, String stationName, int t) {
checkInMap.put(id, new SimpleEntry(stationName, t));
}
public void checkOut(int id, String stationName, int t) {
SimpleEntry<String, Integer> checkInTime = checkInMap.get(id);
SimpleEntry<String, String> startEndStationsKey = new SimpleEntry<>(checkInTime.getKey(), stationName);
int[] timesCount = new int[]{t - checkInTime.getValue(), 1};
totalTimeToCountMap.merge(startEndStationsKey, timesCount, (oldVal, newVal) -> {
oldVal[0]+= newVal[0];
oldVal[1]+= newVal[1];
return oldVal;
});
}
public double getAverageTime(String startStation, String endStation) {
SimpleEntry<String, String> key = new SimpleEntry<>(startStation, endStation);
int[] countTimes = totalTimeToCountMap.get(key);
return (double)countTimes[0]/countTimes[1];
}
public static void main(String[] args) {
UndergroundSystem undergroundSystem = new UndergroundSystem();
undergroundSystem.checkIn(45, "Leyton", 3);
undergroundSystem.checkIn(32, "Paradise", 8);
undergroundSystem.checkIn(27, "Leyton", 10);
undergroundSystem.checkOut(45, "Waterloo", 15);
undergroundSystem.checkOut(27, "Waterloo", 20);
undergroundSystem.checkOut(32, "Cambridge", 22);
System.out.println(undergroundSystem.getAverageTime("Paradise", "Cambridge"));
System.out.println(undergroundSystem.getAverageTime("Leyton", "Waterloo"));
undergroundSystem.checkIn(10, "Leyton", 24);
System.out.println(undergroundSystem.getAverageTime("Leyton", "Waterloo"));
undergroundSystem.checkOut(10, "Waterloo", 38);
System.out.println(undergroundSystem.getAverageTime("Leyton", "Waterloo"));
}
}
Complexity Analysis:
Time complexity: Above code runs in O(1) since we are using HashMap
Space complexity: O(n), since we are storing information into HashMapn(startStation, endStation)
Above implementations source code can be found at