1396. Design Underground System - Explanation

Problem Link



1. Two HashMaps

class UndergroundSystem:

    def __init__(self):
        self.checkInMap = {} # id -> (startStation, time)
        self.routeMap = {} # (start, end) -> [totalTime, count]

    def checkIn(self, id: int, startStation: str, t: int) -> None:
        self.checkInMap[id] = (startStation, t)

    def checkOut(self, id: int, endStation: str, t: int) -> None:
        startStation, time = self.checkInMap[id]
        route = (startStation, endStation)
        if route not in self.routeMap:
            self.routeMap[route] = [0, 0]
        self.routeMap[route][0] += t - time
        self.routeMap[route][1] += 1

    def getAverageTime(self, startStation: str, endStation: str) -> float:
        totalTime, count = self.routeMap[(startStation, endStation)]
        return totalTime / count

Time & Space Complexity

  • Time complexity:
    • O(1)O(1) time for initialization.
    • O(1)O(1) time for each checkIn()checkIn() function call.
    • O(m)O(m) time for each checkOut()checkOut() and getAverageTime()getAverageTime() function calls.
  • Space complexity: O(n+N2)O(n + N ^ 2)

Where nn is the number of passengers, NN is the total number of stations, and mm is the average length of station name.


2. Two HashMaps + Hashing

class UndergroundSystem:
    MOD1, MOD2 = 768258391, 685683731
    BASE1, BASE2 = 37, 31

    def __init__(self):
        self.checkInMap = {}  # id -> (startStation, time)
        self.routeMap = {}  # hash(route) -> (totalTime, count)

    def getHash(self, s1: str, s2: str) -> int:
        h1, h2, p1, p2 = 0, 0, 1, 1
        for c in s1 + ',' + s2:
            h1 = (h1 + (ord(c) - 96) * p1) % self.MOD1
            h2 = (h2 + (ord(c) - 96) * p2) % self.MOD2
            p1 = (p1 * self.BASE1) % self.MOD1
            p2 = (p2 * self.BASE2) % self.MOD2
        return (h1 << 32) | h2

    def checkIn(self, id: int, startStation: str, t: int) -> None:
        self.checkInMap[id] = (startStation, t)

    def checkOut(self, id: int, endStation: str, t: int) -> None:
        startStation, time = self.checkInMap[id]
        routeHash = self.getHash(startStation, endStation)
        if routeHash not in self.routeMap:
            self.routeMap[routeHash] = [0, 0]
        self.routeMap[routeHash][0] += t - time
        self.routeMap[routeHash][1] += 1

    def getAverageTime(self, startStation: str, endStation: str) -> float:
        routeHash = self.getHash(startStation, endStation)
        totalTime, count = self.routeMap[routeHash]
        return totalTime / count

Time & Space Complexity

  • Time complexity:
    • O(1)O(1) time for initialization.
    • O(1)O(1) time for each checkIn()checkIn() function call.
    • O(m)O(m) time for each checkOut()checkOut() and getAverageTime()getAverageTime() function calls.
  • Space complexity: O(n+N2)O(n + N ^ 2)

Where nn is the number of passengers, NN is the total number of stations, and mm is the average length of station name.