Track the User with the Most Distinct Contacts: O(1) Query and Top-K for Changing k

Quick Overview

Design a class that records undirected messages between users and returns the user who has talked with the most distinct people, then make that query constant time and add a top-K query whose k changes on every call. It tests deduplication with hash sets, space analysis of per-user sets, and incremental ranking structures.

Track the User with the Most Distinct Contacts: O(1) Query and Top-K for Changing k

Company: Google

Role: Software Engineer

Category: Software Engineering Fundamentals

Difficulty: medium

Interview Round: Technical Screen

Users send each other messages. Each message is between two users, and messages are **undirected**: a message between `A` and `B` counts as contact for both `A` and `B`. Design a class that supports two operations: - `register(a, b)` records a message between users `a` and `b`. - `most_active_user()` returns the user who has exchanged messages with the **largest number of distinct users**. The problem builds up over three parts. Throughout, analyze time and space complexity carefully, including the memory held by every per-user collection. ### Clarifying Questions - Does messaging the same person many times count once or many times toward a user's activity? - If several users tie for the most distinct contacts, which one should be returned? - What should `most_active_user()` return before any message has been registered? - Can a user message themselves, and does that count? - Which is more frequent, `register` or the queries? Can messages ever be removed? ### Part 1 — Register messages and find the most active user Implement `register(a, b)` and `most_active_user()`. Then state the time complexity of each operation and the space complexity of the whole structure. ```hint Count what is distinct A second message between the same two users must not raise either user's count, so decide what you must remember about each user to recognize a repeat contact. ``` #### What This Part Should Cover - Correct deduplication of repeat contacts, applied to both users in the message - Time complexity per operation - A space bound that accounts for every stored contact, including the worst case where many pairs of users have talked ### Part 2 — Make the query constant time Optimize `most_active_user()` to run in O(1) while keeping `register` efficient. ```hint What can a single message change? Look at how much one call to `register` can change the counts, and whose standing it can affect. ``` #### What This Part Should Cover - An invariant that keeps the answer current after every `register` - An argument for why the invariant holds, including ties - The cost this moves into `register` ### Part 3 — Top K with a changing k Add `top_k(k)`, which returns the `k` users with the most distinct contacts, ordered from most to fewest. The value of `k` can differ on every call, so a heap tied to one fixed `k` is not enough. Sorting all users on every call is the baseline to beat. ```hint Exploit how counts move Counts only ever grow, and each change is small. Ask what kind of structure could stay in order cheaply under exactly that kind of change. ``` #### Clarifying Questions for this Part - If `k` is larger than the number of users, should the result contain every user, or is that an error? - Must users with equal counts appear in a fixed order? #### What This Part Should Cover - The cost of the baselines: sorting, or building a size-`k` heap on every call - A structure whose query cost depends on `k` rather than on the number of users - The update cost in `register` and the extra space used - A tie rule that makes the output deterministic ### What a Strong Answer Covers - Duplicates, ties, and the empty state clarified before coding - Clean, working code for each part, with each part building on the previous one - Correct complexity analysis, especially the space held by the contact sets - A comparison of at least two approaches to top K, with the trade-offs stated - Clear narration of each step while coding ### Follow-up Questions - Messages can now be deleted, so counts can go down. Which of your structures still work, and what has to change? - The message volume no longer fits on one machine. How would you compute the global most active user and top K across shards? - Storing every contact set is too expensive. What would you give up to estimate distinct-contact counts in far less memory?

Overview: Design a class that records undirected messages between users and returns the user who has talked with the most distinct people, then make that query constant time and add a top-K query whose k changes on every call. It tests deduplication with hash sets, space analysis of per-user sets, and incremental ranking structures.

|Home/Software Engineering Fundamentals/Google
Google logo
Google
Sep 8, 2026
mediumSoftware EngineerTechnical ScreenSoftware Engineering Fundamentals
0
0

Users send each other messages. Each message is between two users, and messages are undirected: a message between A and B counts as contact for both A and B. Design a class that supports two operations:

  • register(a, b) records a message between users a and b .
  • most_active_user() returns the user who has exchanged messages with the largest number of distinct users .

The problem builds up over three parts. Throughout, analyze time and space complexity carefully, including the memory held by every per-user collection.

Clarifying Questions Guidance

  • Does messaging the same person many times count once or many times toward a user's activity?
  • If several users tie for the most distinct contacts, which one should be returned?
  • What should most_active_user() return before any message has been registered?
  • Can a user message themselves, and does that count?
  • Which is more frequent, register or the queries? Can messages ever be removed?

Part 1 — Register messages and find the most active user

Implement register(a, b) and most_active_user(). Then state the time complexity of each operation and the space complexity of the whole structure.

What This Part Should Cover Guidance

  • Correct deduplication of repeat contacts, applied to both users in the message
  • Time complexity per operation
  • A space bound that accounts for every stored contact, including the worst case where many pairs of users have talked

Part 2 — Make the query constant time

Optimize most_active_user() to run in O(1) while keeping register efficient.

What This Part Should Cover Guidance

  • An invariant that keeps the answer current after every register
  • An argument for why the invariant holds, including ties
  • The cost this moves into register

Part 3 — Top K with a changing k

Add top_k(k), which returns the k users with the most distinct contacts, ordered from most to fewest. The value of k can differ on every call, so a heap tied to one fixed k is not enough. Sorting all users on every call is the baseline to beat.

Clarifying Questions for this Part Guidance

  • If k is larger than the number of users, should the result contain every user, or is that an error?
  • Must users with equal counts appear in a fixed order?

What This Part Should Cover Guidance

  • The cost of the baselines: sorting, or building a size- k heap on every call
  • A structure whose query cost depends on k rather than on the number of users
  • The update cost in register and the extra space used
  • A tie rule that makes the output deterministic

What a Strong Answer Covers Guidance

  • Duplicates, ties, and the empty state clarified before coding
  • Clean, working code for each part, with each part building on the previous one
  • Correct complexity analysis, especially the space held by the contact sets
  • A comparison of at least two approaches to top K, with the trade-offs stated
  • Clear narration of each step while coding

Follow-up Questions Guidance

  • Messages can now be deleted, so counts can go down. Which of your structures still work, and what has to change?
  • The message volume no longer fits on one machine. How would you compute the global most active user and top K across shards?
  • Storing every contact set is too expensive. What would you give up to estimate distinct-contact counts in far less memory?
Loading comments...