PracHub
QuestionsPremiumCoachesLearningGuidesInterview Prep

Quick Overview

This question evaluates graph and tree reasoning, algorithmic aggregation for computing descendant counts, and system-level thinking for incremental updates and recursion-depth mitigation.

  • medium
  • Robinhood
  • Coding & Algorithms
  • Software Engineer

Count Referral Descendants

Company: Robinhood

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: medium

Interview Round: Technical Screen

You are building a referral analytics feature. Each referral relationship is represented as a directed pair `(referrer, referredUser)`, meaning `referrer` directly invited `referredUser`. A user may directly refer many users, but each user has at most one direct referrer. Assume the referral graph is acyclic, so it forms one or more rooted trees. Given a list of referral pairs, compute for every user the total number of users in their referral network, including both direct and indirect referrals. In other words, for each user, return the number of descendants reachable from that user. Example: ```text referrals = [ ("A", "B"), ("A", "C"), ("B", "D"), ("B", "E"), ("C", "F") ] ``` Expected result: ```text A -> 5 B -> 2 C -> 1 D -> 0 E -> 0 F -> 0 ``` Requirements: 1. Return a mapping from every user appearing in the input to their total referral count. 2. Explain the time and space complexity. 3. Discuss how you would find the top 3 users by referral count efficiently. 4. Discuss how you would avoid recursion-depth issues for very deep referral chains. 5. Follow-up: suppose this is an online production system where referral relationships are continuously added. The graph is very large, and recomputing all counts after every insertion is too expensive. Design an approach to support incremental updates when a new referral edge is added.

Quick Answer: This question evaluates graph and tree reasoning, algorithmic aggregation for computing descendant counts, and system-level thinking for incremental updates and recursion-depth mitigation.

Part 1: Compute Total Referral Descendant Counts

You are given a list of referral relationships. Each pair (referrer, referredUser) means referrer directly invited referredUser. Each user has at most one direct referrer, and the graph is acyclic, so it forms one or more rooted trees. Return a mapping from every user appearing in the input to the total number of direct and indirect referrals reachable from that user.

Constraints

  • 0 <= len(referrals) <= 100000
  • User IDs are non-empty strings.
  • Each referred user has at most one direct referrer.
  • The referral graph is acyclic.
  • Referral pairs are unique.

Examples

Input: ([('A', 'B'), ('A', 'C'), ('B', 'D'), ('B', 'E'), ('C', 'F')],)

Expected Output: {'A': 5, 'B': 2, 'C': 1, 'D': 0, 'E': 0, 'F': 0}

Explanation: A reaches B, C, D, E, and F. B reaches D and E. C reaches F.

Input: ([],)

Expected Output: {}

Explanation: No users appear in the input, so the result is empty.

Input: ([('root', 'child')],)

Expected Output: {'root': 1, 'child': 0}

Explanation: root has one direct referral, and child has none.

Input: ([('A', 'B'), ('C', 'D'), ('C', 'E')],)

Expected Output: {'A': 1, 'B': 0, 'C': 2, 'D': 0, 'E': 0}

Explanation: The input contains two separate referral trees.

Input: ([('A', 'B'), ('B', 'C'), ('C', 'D')],)

Expected Output: {'A': 3, 'B': 2, 'C': 1, 'D': 0}

Explanation: This is a chain, so each earlier user reaches all later users.

Hints

  1. A user's answer is the sum of 1 plus the descendant count of each direct child.
  2. Process children before parents, for example with postorder DFS or an explicit stack.

Part 2: Find the Top 3 Users by Referral Count

Given referral relationships forming an acyclic referral forest, return the user IDs of the top 3 users with the largest total referral networks. A user's referral count includes all direct and indirect descendants. If fewer than 3 users appear, return all of them. Sort the result by descending referral count, breaking ties by lexicographically smaller user ID.

Constraints

  • 0 <= len(referrals) <= 100000
  • User IDs are non-empty strings.
  • Each referred user has at most one direct referrer.
  • The referral graph is acyclic.
  • Referral pairs are unique.

Examples

Input: ([('A', 'B'), ('A', 'C'), ('B', 'D'), ('B', 'E'), ('C', 'F')],)

Expected Output: ['A', 'B', 'C']

Explanation: Counts are A=5, B=2, C=1, and leaves=0.

Input: ([],)

Expected Output: []

Explanation: No users appear, so there are no top users.

Input: ([('A', 'B')],)

Expected Output: ['A', 'B']

Explanation: There are only two users. A has count 1 and B has count 0.

Input: ([('A', 'D'), ('B', 'E'), ('C', 'F')],)

Expected Output: ['A', 'B', 'C']

Explanation: A, B, and C all have count 1, so lexicographic order breaks the tie.

Input: ([('A', 'B'), ('B', 'C'), ('D', 'E'), ('F', 'G')],)

Expected Output: ['A', 'B', 'D']

Explanation: Counts are A=2, B=1, D=1, F=1, and leaves=0. B beats D and F by lexicographic order; D beats F.

Hints

  1. First compute each user's descendant count using a postorder traversal.
  2. Because only 3 users are needed, you do not need to sort every user by count.

Part 3: Count Descendants Without Recursion

Referral chains can be very deep, and a recursive DFS may exceed the call-stack limit. Given referral pairs and a starting user, return how many users are reachable from that starting user using an iterative traversal.

Constraints

  • 0 <= len(referrals) <= 200000
  • User IDs are non-empty strings.
  • Each referred user has at most one direct referrer.
  • The referral graph is acyclic.
  • Referral depth may exceed the language recursion limit, so the solution must not rely on recursion.

Examples

Input: ([('A', 'B'), ('A', 'C'), ('B', 'D'), ('B', 'E'), ('C', 'F')], 'A')

Expected Output: 5

Explanation: A reaches B, C, D, E, and F.

Input: ([('A', 'B'), ('A', 'C'), ('B', 'D'), ('B', 'E'), ('C', 'F')], 'B')

Expected Output: 2

Explanation: B reaches D and E.

Input: ([], 'A')

Expected Output: 0

Explanation: There are no referral edges.

Input: ([('A', 'B'), ('A', 'C')], 'C')

Expected Output: 0

Explanation: C is a leaf user.

Input: ([('0', '1'), ('1', '2'), ('2', '3'), ('3', '4'), ('4', '5'), ('5', '6'), ('6', '7'), ('7', '8'), ('8', '9'), ('9', '10')], '0')

Expected Output: 10

Explanation: The start user is at the head of a chain of 10 descendants.

Hints

  1. Build an adjacency list from each referrer to their direct referred users.
  2. Use an explicit stack or queue instead of recursive function calls.

Part 4: Incremental Referral Count Queries

You are maintaining referral counts while referral edges are added over time. Operations arrive in order. An add operation adds a valid new edge from referrer to referredUser. The referred user may already be a root of an existing referral subtree, but it does not currently have a direct referrer. A query operation asks for a user's current total number of direct and indirect referrals. Return the answers to all query operations without recomputing every user's count after each insertion.

Constraints

  • 0 <= len(operations) <= 100000
  • User IDs are non-empty strings.
  • Every add operation is valid: the referred user has no current direct referrer, the edge is not a duplicate, and adding it does not create a cycle.
  • Users may appear for the first time in either add or query operations.
  • The total number of ancestor links walked across all add operations is at most 300000.

Examples

Input: ([('query', 'A'), ('add', 'A', 'B'), ('query', 'A'), ('query', 'B')],)

Expected Output: [0, 1, 0]

Explanation: Initially A is unknown, so its count is 0. After A refers B, A has one descendant and B has none.

Input: ([('add', 'B', 'C'), ('add', 'B', 'D'), ('query', 'B'), ('add', 'A', 'B'), ('query', 'A'), ('query', 'B')],)

Expected Output: [2, 3, 2]

Explanation: B first has descendants C and D. When A refers B, A gains B plus B's two descendants.

Input: ([('add', 'A', 'B'), ('add', 'B', 'C'), ('query', 'A'), ('add', 'C', 'D'), ('query', 'A'), ('query', 'B'), ('query', 'C'), ('query', 'D')],)

Expected Output: [2, 3, 2, 1, 0]

Explanation: Adding D under C increases the counts of C, B, and A.

Input: ([('add', 'X', 'Y'), ('add', 'A', 'B'), ('query', 'X'), ('query', 'A'), ('query', 'Z')],)

Expected Output: [1, 1, 0]

Explanation: X and A are separate roots. Unknown user Z has count 0.

Input: ([],)

Expected Output: []

Explanation: No operations means no query answers.

Hints

  1. When adding referrer -> referredUser, referrer and all ancestors of referrer gain the entire subtree rooted at referredUser.
  2. Maintain parent pointers and current descendant counts so that queries are dictionary lookups.
Last updated: Jun 21, 2026

Loading coding console...

PracHub

Master your tech interviews with 8,000+ real questions from top companies.

Product

  • Questions
  • Learning Tracks
  • Interview Guides
  • Resources
  • Premium
  • For Universities
  • Student Access

Browse

  • By Company
  • By Role
  • By Category
  • Topic Hubs
  • SQL Questions
  • Compare Platforms
  • Discord Community

Support

  • support@prachub.com
  • (916) 541-4762

Legal

  • Privacy Policy
  • Terms of Service
  • About Us

© 2026 PracHub. All rights reserved.

Related Coding Questions

  • Build a Weekly Calendar - Robinhood (medium)
  • Solve path and inventory problems - Robinhood
  • Implement Calendar Layout and String Packing - Robinhood (medium)
  • Aggregate user logs into 30-minute sessions - Robinhood (hard)
  • Compute dependency load factors in a DAG - Robinhood (medium)