Problem · Stack

Most Frequent Call Path From Function Trace Logs

MediumRobloxPHONE SCREEN
See Roblox hiring insights

You are given a list of single-threaded trace logs from a program. Each log records either entering a function or returning from a function. While scanning the logs from left to right, maintain the active call stack.

Every time a function is entered, count the full active call path from the root function to the current leaf function. Paths are represented by joining function names with ->. For example, if the active stack after an entry is main -> handleEvents -> handleClickEvent, the counted path is main->handleEvents->handleClickEvent.

Return the call path that occurs most often. If multiple paths have the same frequency, return the deeper path. If frequency and depth are both tied, return the path that first reached the tied frequency while scanning left to right.

The final tie-breaker is not the first time a path appears. It is the first time a path's count reaches the tied best count. For example, if one path appears earlier but reaches count 2 after another same-depth path reaches count 2, the path that reached count 2 first wins.

Each trace line is formatted as "-> name" for an entry or "<- name" for a return. A robust parser should also accept lines without a space after the arrow, such as "->main" and "<-main". Assume the trace is well-formed: every return matches the top of the current stack.

Follow-up variants include returning the frequency with the path, handling multiple prompt IDs with independent stacks, returning the longest active stack, and finding the most frequent function per prompt.

Examples
01 · Example 1
traces = ["-> main", "-> handleEvents", "-> handleClickEvent", "<- handleClickEvent", "-> handleClickEvent", "<- handleClickEvent", "<- handleEvents", "<- main"]
return = "main->handleEvents->handleClickEvent"
The paths main and main->handleEvents are each counted once. The path main->handleEvents->handleClickEvent is counted twice, so it is returned.
02 · Example 2
traces = ["-> main", "-> handleEvents", "-> handleKeyEvent", "<- handleKeyEvent", "-> handleClickEvent", "<- handleClickEvent", "-> handleClickEvent", "<- handleClickEvent", "-> handleKeyEvent", "<- handleKeyEvent", "<- handleEvents", "<- main"]
return = "main->handleEvents->handleClickEvent"
The handleKeyEvent path appears before handleClickEvent, but that is not the final tie-breaker. Both leaf paths occur twice and have the same depth, and handleClickEvent reaches count 2 before handleKeyEvent reaches count 2, so handleClickEvent wins.
03 · Example 3
traces = ["-> A", "-> B", "<- B", "<- A"]
return = "A->B"
A and A->B both occur once. A->B is deeper, so it wins the tie.
04 · Example 4
traces = []
return = ""
There are no entered functions, so the answer is the empty string.
05 · Example 5
traces = ["->main", "->worker", "<-worker", "<-main"]
return = "main->worker"
The parser should accept trace lines without spaces after the arrow. The deeper path wins because both paths occur once.
Constraints
  • 0 <= traces.length
  • Each non-empty trace is an entry line beginning with -> or an exit line beginning with <-.
  • Function names contain letters, digits, or underscores.
  • The trace is well-formed and balanced unless the interviewer says otherwise.
  • Call depth is bounded by the number of trace lines.
More Roblox problems
drafts saved locally
public String mostFrequentCallPath(String[] traces) {
  // write your code here
}
traces["-> main", "-> handleEvents", "-> handleClickEvent", "<- handleClickEvent", "-> handleClickEvent", "<- handleClickEvent", "<- handleEvents", "<- main"]
expected"main->handleEvents->handleClickEvent"
sign in to submit