Design a Customer Revenue Index with Referrals and Threshold Queries
DatabricksSoftware Engineer · Technical ScreenLast updated
Tests designing an in-memory index that tracks direct and referral revenue across customers and efficiently supports threshold-bounded minimum revenue queries using balanced search trees.
Problem Statement
Design an in-memory revenue tracking system, CustomerRevenueTracker, that monitors customer revenue including referral bonuses and supports range-based threshold queries.
Each customer can have an optional direct referrer. When a customer earns direct revenue, both that customer's total revenue and their direct referrer's total revenue (if one exists) increase by that amount. Referral credits do not propagate beyond one level (i.e., strictly direct referrals).
You need to implement the CustomerRevenueTracker class with the following methods:
__init__(): Initializes the data structure.register_customer(customer_id: int, referrer_id: int | None) -> None: Registers a new customer with an optional existing referrer. A customer ID is guaranteed to be unique and never registered more than once. Ifreferrer_idis provided, it is guaranteed thatreferrer_idhas already been registered. Initial revenue for a new customer is0.add_revenue(customer_id: int, amount: int) -> None: Addsamount(amount > 0) tocustomer_id's direct revenue. This also credits the sameamountto their direct referrer's total revenue (if they have one).get_lowest_revenue_above(threshold: int) -> int | None: Returns thecustomer_idof the customer whose total revenue is greater than or equal tothreshold, and has the lowest total revenue among all such customers. If multiple customers tie for the lowest total revenue above or equal tothreshold, return the customer with the smallestcustomer_id. If no customer meets the threshold, returnNone.
Example
tracker = CustomerRevenueTracker()
tracker.register_customer(1, None) # Customer 1 has no referrer
tracker.register_customer(2, 1) # Customer 2 referred by 1
tracker.register_customer(3, 1) # Customer 3 referred by 1
tracker.add_revenue(2, 50)
# Customer 2 direct: 50, total: 50
# Customer 1 referral: 50, direct: 0, total: 50
# Customer 3 total: 0
tracker.add_revenue(3, 30)
# Customer 3 direct: 30, total: 30
# Customer 1 referral: 80, direct: 0, total: 80
print(tracker.get_lowest_revenue_above(40))
# Customers >= 40 are Customer 2 (50) and Customer 1 (80).
# Lowest total revenue is 50 -> Customer 2.
# Output: 2
print(tracker.get_lowest_revenue_above(50))
# Customer 2 (50) and Customer 1 (80) both >= 50. Lowest is 50 -> Customer 2.
# Output: 2
print(tracker.get_lowest_revenue_above(90))
# Output: None
Constraints
1 <= customer_id, referrer_id <= 10^91 <= amount <= 10^60 <= threshold <= 10^12- At most
2 * 10^5total calls toregister_customer,add_revenue, andget_lowest_revenue_abovecombined. - Optimal target time complexity:
register_customer:O(log N)add_revenue:O(log N)get_lowest_revenue_above:O(log N)whereNis the number of registered customers.
Hints
Hint 1
Maintain each customer's current total revenue and referrer in a hash map for O(1) lookups.
Hint 2
Use an ordered set or balanced binary search tree storing `(total_revenue, customer_id)` tuples to support lower-bound queries.
Hint 3
When modifying a customer's total revenue, remember to remove their old `(total_revenue, customer_id)` entry from the ordered structure before inserting the updated entry.
Follow-up questions
- How would you handle multi-level (hierarchical) referral propagation where each ancestor receives a decreasing fraction of revenue?
- If updates are extremely frequent while threshold queries are rare, how would you change the indexing strategy to optimize write throughput?
- How would you make this data structure thread-safe for concurrent read and write operations without taking a global lock?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.