Visit-Pattern Counter: Multi-Input Runtime Analysis and Production Hardening
Company: Spotify
Role: Backend Engineer
Category: Software Engineering Fundamentals
Difficulty: medium
Interview Round: Onsite
In a backend coding round, once you have a working function for the problem below, the interviewer spends the remaining time on follow-ups about what it costs and how you would get it ready for production code.
**The function.** You receive three lists of equal length, `usernames`, `timestamps` and `websites`. Record `i` says that user `usernames[i]` visited website `websites[i]` at time `timestamps[i]`, and the records arrive in no particular order. A **pattern** is an ordered list of three website names, repeats allowed (`["home", "home", "cart"]` is valid). A user **follows** a pattern if its three websites appear in that order, not necessarily next to each other, in that user's visits sorted by time. A pattern's **score** is the number of distinct users who follow it. The function returns the highest-scoring pattern; among tied patterns it returns the lexicographically smallest, comparing the first names, then the second, then the third.
Begin by stating the approach your implementation uses, since both follow-ups depend on it.
### Clarifying Questions
- Can one user have two visits with the same timestamp, and if so, which one counts as earlier?
- What should the function do when no user has at least three visits?
- Will callers always want patterns of length three?
- How are records typically distributed: many users with short histories, or a few users with very long ones, and how many distinct websites are there?
### Part 1 — Runtime and memory across the inputs
The problem has several independent inputs, so a single n hides where the cost comes from. Express the time and memory of your approach in terms of the total number of records, the number of distinct users, the longest single-user history and the number of distinct website names. Say which term dominates, which input shape is the worst case, and how the cost changes when the same records are spread over many users instead of concentrated in one. Then explain what you would change if one user's history could be far longer than the number of distinct websites that user visits.
```hint Work per user first
Write down the cost for a single user with a given number of visits, then add it up over users whose visit counts sum to the total.
```
#### What This Part Should Cover
- The cost of each phase (grouping and ordering, pattern generation, counting, choosing the winner) in the named dimensions
- How the dominant term behaves as records are spread out or concentrated, and the worst-case input shape
- Bounds on the number of distinct patterns that come from the website vocabulary as well as from history length
- Whether per-user work can depend on distinct websites rather than visit count, and when that is worth the extra code
### Part 2 — Changes before it ships in production code
The team wants to merge your function into a production codebase. Describe the functional changes (interface, return value, input handling, behavior on edge cases) and the style changes (naming, decomposition, typing, documentation, tests) you would make, and give the reason for each.
```hint List the silent assumptions
Every guarantee the interview version took for granted has to become a validation, a documented policy, or part of a type.
```
#### What This Part Should Cover
- Interface and return-type changes that remove silent preconditions
- Explicit policies for ambiguous input, with the tie rule kept deterministic
- Decomposition and naming that make each step testable on its own
- A test plan, including how any optimized path is checked against a simple reference
### What a Strong Answer Covers
- Complexity stated in consistently named dimensions, with a justified worst-case input shape
- Distinct-user counting and the tie rule preserved by every proposed change
- Trade-offs between simpler code and a faster per-user step, tied to the expected input shapes
- Production changes motivated by concrete failure modes rather than generic style advice
### Follow-up Questions
- If the visit log were too large for one machine, how would you split grouping, per-user pattern extraction and counting across workers while keeping the tie rule deterministic?
- How do the analysis and the code change if callers need patterns of length k instead of three?
- Should the function return every tied pattern instead of one, and what would that change for callers?
Overview: A Spotify backend coding follow-up: for a function that finds the three-website visit pattern followed by the most distinct users, analyze time and memory using separate input dimensions such as records, users, longest per-user history and distinct sites. It also asks which functional and style changes the code needs before it ships in production.
Read the full Spotify Backend Engineer interview experience this question came from