Design Underground System

Medium DesignHash Map

Problem

Track travel times between stations on a subway network. Implement void checkIn(int id, String stationName, int t) — customer id enters at stationName at time t; void checkOut(int id, String stationName, int t) — customer id exits at stationName at time t; double getAverageTime(String startStation, String endStation) — the average travel time of all customers who went directly from startStation to endStation.

Example 1 Input: checkIn(1,"A",3); checkOut(1,"B",8); checkIn(2,"A",10); checkOut(2,"B",16); getAverageTime("A","B") Output: 5.5

Constraints

Approach — Hashing & Counting

This is a Hashing & Counting problem. The idea: store what you've seen in a hash map for O(1) lookups, trading a little space to avoid a nested scan. Work through the reference code below line by line, then re-derive it yourself in the editor — that's how the pattern sticks.

Complexity: O(n) time, O(n) space.

Solution code

Python

class UndergroundSystem:
    def __init__(self):
        self.checked = {}      # id -> (station, time)
        self.totals = {}       # (start, end) -> [total_time, count]

    def checkIn(self, id, stationName, t):
        self.checked[id] = (stationName, t)

    def checkOut(self, id, stationName, t):
        start, t0 = self.checked.pop(id)
        key = (start, stationName)
        rec = self.totals.setdefault(key, [0, 0])
        rec[0] += t - t0
        rec[1] += 1

    def getAverageTime(self, startStation, endStation):
        total, count = self.totals[(startStation, endStation)]
        return total / count

Java

import java.util.HashMap;
import java.util.Map;

class UndergroundSystem {
    // id -> [startStation, checkInTime]
    private Map<Integer, Object[]> checkedIn;
    // "start->end" -> [totalTime, tripCount]
    private Map<String, double[]> routeStats;

    public UndergroundSystem() {
        checkedIn = new HashMap<>();
        routeStats = new HashMap<>();
    }

    public void checkIn(int id, String stationName, int t) {
        checkedIn.put(id, new Object[]{stationName, t});
    }

    public void checkOut(int id, String stationName, int t) {
        Object[] entry = checkedIn.remove(id);
        String start = (String) entry[0];
        int startTime = (int) entry[1];
        String route = start + "->" + stationName;
        double[] stats = routeStats.computeIfAbsent(route, k -> new double[2]);
        stats[0] += t - startTime;
        stats[1] += 1;
    }

    public double getAverageTime(String startStation, String endStation) {
        double[] stats = routeStats.get(startStation + "->" + endStation);
        return stats[0] / stats[1];
    }
}

Practice it

Reading a solution isn't the same as being able to write it under pressure. Open this problem in the in-browser editor, hide the solution, and solve it from scratch — your code runs against real test cases instantly.

Solve Design Underground System interactively → ← All solutions