Build User Journey Path Summary
WhatnotSoftware Engineer · Technical ScreenLast updated
This question evaluates the ability to transform unordered user action logs into a trie-like path tree, exercising skills in grouping and time-sorting per user, maintaining stable insertion order, counting distinct users per prefix, and producing deterministic preorder string output.
Implement a function build_summary(logs) -> str that summarizes user journeys as a trie-like path tree.
You are given a list of action logs. Each log has the form:
(user_id: int, time: int, action: str)
Each user may have multiple logs. For each user, sort that user's logs by time in ascending order to obtain the user's action sequence. Then build a tree where each root-to-node path represents an action-prefix taken by at least one user. Each node stores the number of distinct users whose journey reached that exact prefix.
Rules:
- Logs may arrive unordered, so sort actions by time per user.
- Each user's journey contributes once to every prefix it traverses.
- Repeated actions are valid and represent distinct steps. For example,
A -> B -> Bis different fromA -> Band should create a childBunder the firstA -> Bnode. - Empty input should return an empty string.
- A single user with a single action should return a one-node tree.
- For deterministic output, print children in the order they are first created while inserting user journeys. Process users in ascending
user_idorder after constructing each user's sorted sequence. - If two logs for the same user have the same timestamp, preserve their original input order.
Output format:
- Return a multiline string.
- Use one line per node.
- Print the action and count as
ACTION (COUNT). - Root-level nodes have no prefix.
- Non-root nodes are prefixed by two spaces per depth level followed by
->. - Print the tree using depth-first preorder traversal.
Example:
Input:
logs = [
(100, 1000, "A"),
(300, 1150, "A"),
(200, 1200, "B"),
(100, 1200, "B"),
(100, 1300, "C"),
(200, 1400, "A"),
(300, 1500, "B"),
(300, 1550, "B"),
(100, 1560, "D"),
]
Per-user sequences after sorting by time:
user 100: A -> B -> C -> D
user 200: B -> A
user 300: A -> B -> B
Expected output:
A (2)
-> B (2)
-> C (1)
-> D (1)
-> B (1)
B (1)
-> A (1)
Additional test cases:
build_summary([])
# ""
build_summary([(1, 100, "X")])
# "X (1)"
build_summary([
(1, 100, "A"),
(1, 200, "B"),
(2, 100, "A"),
(2, 200, "B"),
])
# "A (2)\n -> B (2)"
build_summary([
(1, 300, "C"),
(1, 100, "A"),
(1, 200, "B"),
])
# "A (1)\n -> B (1)\n -> C (1)"
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.