209. Design Website Customer Visit Tracking Service
Asked in
Design Website Customer Visit Tracking Service

Design a customer visit tracking service for a website that receives millions of visits every day. Each customer has a unique identifier that remains the same across all their visits.

A customer is a one-time visitor if they have visited exactly once so far. A customer is a recurrent visitor if they have visited more than once.

The service should record customer visits, return a customer's latest login timestamp, and return the first customer who is still a one-time visitor.

Rules

  • Visit timestamps are integers and are passed as currentTimestamp.
  • Calls to postCustomerVisit will have monotonically non-decreasing currentTimestamp values.
  • If multiple one-time visitors have the same first visit timestamp, return the lexicographically smaller customer identifier.
  • If there is no one-time visitor, return an empty string.
  • If a customer has never visited, their latest login timestamp is -1.

Class and Method Signatures

CustomerVisitTracker()

  • Initializes an empty customer visit tracking service.

void postCustomerVisit(String customerId, int currentTimestamp)

  • Records a visit by customerId at currentTimestamp.
  • On the first visit, the customer becomes a one-time visitor.
  • On the second or later visit, the customer becomes a recurrent visitor and is no longer a one-time visitor.

int getLastLoginTimestamp(String customerId)

  • Returns the latest visit timestamp of customerId.
  • Returns -1 if customerId has never visited.

String getFirstOneTimeVisitor()

  • Returns the customer identifier of the earliest customer who still has exactly one visit.
  • If there is a tie by first visit timestamp, returns the lexicographically smaller customer identifier.
  • Returns an empty string if no one-time visitor exists.

Constraints

  • 1 ≤ customerId.length() ≤ 100
  • customerId contains only lowercase English letters, uppercase English letters, and digits.
  • 0 ≤ currentTimestamp ≤ 1,000,000,000
  • The total number of method calls will be at most 1,000,000.

Examples

Example 1

CustomerVisitTracker tracker = new CustomerVisitTracker()

tracker.postCustomerVisit(customerId = "alice", currentTimestamp = 10)

tracker.postCustomerVisit(customerId = "bob", currentTimestamp = 15)

tracker.getFirstOneTimeVisitor()

Output: "alice"

Explanation: Both customers have exactly one visit, but "alice" became a one-time visitor earlier.

Example 2

CustomerVisitTracker tracker = new CustomerVisitTracker()

tracker.postCustomerVisit(customerId = "john", currentTimestamp = 20)

tracker.postCustomerVisit(customerId = "mike", currentTimestamp = 25)

tracker.postCustomerVisit(customerId = "john", currentTimestamp = 30)

tracker.getFirstOneTimeVisitor()

Output: "mike"

Explanation: "john" has visited twice, so only "mike" is still a one-time visitor.

Example 3

CustomerVisitTracker tracker = new CustomerVisitTracker()

tracker.postCustomerVisit(customerId = "cust2", currentTimestamp = 100)

tracker.postCustomerVisit(customerId = "cust1", currentTimestamp = 100)

tracker.getFirstOneTimeVisitor()

Output: "cust1"

Explanation: Both customers have the same first visit timestamp, so the lexicographically smaller customer identifier is returned.

Example 4

CustomerVisitTracker tracker = new CustomerVisitTracker()

tracker.postCustomerVisit(customerId = "tom", currentTimestamp = 5)

tracker.getLastLoginTimestamp(customerId = "tom")

Output: 5

tracker.postCustomerVisit(customerId = "tom", currentTimestamp = 50)

tracker.getLastLoginTimestamp(customerId = "tom")

Output: 50

Explanation: The latest login timestamp for "tom" is updated after each visit.

Example 5

CustomerVisitTracker tracker = new CustomerVisitTracker()

tracker.postCustomerVisit(customerId = "a1", currentTimestamp = 7)

tracker.postCustomerVisit(customerId = "a1", currentTimestamp = 9)

tracker.getFirstOneTimeVisitor()

Output: ""

Explanation: The only customer is recurrent, so there is no one-time visitor.



Please use Laptop/Desktop or any other large screen to add/edit code.