You are processing a chronological stream of server hit records. Each record contains an IP address as a string.
Design and implement a component that supports the following operations:
-
recordHit(ip: string)
: Add a new server hit from
ip
.
-
getFirstUniqueIp() -> string | null
: Return the earliest IP address in the stream that has appeared exactly once so far. If no such IP exists, return
null
.
Example:
recordHit("10.0.0.1")
recordHit("10.0.0.2")
recordHit("10.0.0.1")
getFirstUniqueIp() -> "10.0.0.2"
recordHit("10.0.0.2")
getFirstUniqueIp() -> null
recordHit("10.0.0.3")
getFirstUniqueIp() -> "10.0.0.3"
Follow-up: How would you scale the solution if the server receives millions or billions of hit records? Discuss memory usage, throughput, and any trade-offs if exact results are required versus approximate results.