Reported July 2026
Netflixdesign

Movie Billboard Rotation

Reported by candidates from Netflix's online assessment. Pattern, common pitfall, and the honest play if you blank under the timer.

Get StealthCoderRuns invisibly during the live Netflix OA. Under 2s to a working solution.
Founder's read

The Netflix Movie Billboard Rotation question, reported in July 2026, looks like a linked list warm-up and then punishes you for treating it like one. You're maintaining a circular rotation where movies get removed and re-added while a cursor keeps moving. The catch is that the cursor sits on a position, not on a movie, so deleting the movie under it changes nothing about where the next call lands. If your cursor points at a node that no longer exists, you're done. This is a design problem with an ordered map plus a reverse map. If you blank on the cursor logic mid-assessment, StealthCoder is the quiet backup running on your screen.

The problem

Process an ordered sequence of operations for a movie billboard. The billboard keeps an active rotation of movie IDs.
["ADD", movieId]: if movieId is inactive, append it to the tail of the rotation and assign it a new monotonically increasing position. Adding an active ID is a no-op.
["REMOVE", movieId]: remove the active movie. Removing a missing ID is a no-op. A later successful re-add receives a new tail position; old positions are never reused.
["NEXT"]: return the active successor after the last displayed position. The first non-empty call returns the active head, and traversal wraps to the head after the tail. If no movie is active, return NONE without moving the cursor.
Only NEXT contributes an element to the returned array, in operation order.
Do not use a heap. Model the active rotation with an ordered position-to-movie map and a movie-to-position map. Multithreading, distributed scaling, and durable storage are follow-up discussion topics and are outside the judged single-threaded core.

Function
rotateBillboard(operations: String[][]) → String[]

Examples
Example 1
operations = [["ADD","A"],["ADD","B"],["ADD","C"],["NEXT"],["NEXT"],["REMOVE","B"],["NEXT"],["ADD","B"],["NEXT"],["NEXT"]]
return = ["A","B","C","B","A"]
The first two calls display A and B. Removing B leaves the cursor at its old position, so the next successor is C. Re-adding B places it after C, then the rotation wraps to A.
Example 2
operations = [["NEXT"],["ADD","x"],["ADD","x"],["NEXT"],["REMOVE","missing"],["NEXT"],["REMOVE","x"],["NEXT"],["ADD","x"],["NEXT"]]
return = ["NONE","x","x","NONE","x"]
An empty rotation returns NONE. Duplicate ADD and missing REMOVE operations do nothing. After removal, re-adding x creates a new active tail entry.
Example 3
operations = [["ADD","a"],["ADD","b"],["ADD","c"],["ADD","d"],["NEXT"],["REMOVE","b"],["REMOVE","c"],["NEXT"],["REMOVE","d"],["NEXT"],["ADD","c"],["NEXT"]]
return = ["a","d","a","c"]
Deleted positions are skipped. After d is removed, the next active position wraps to a. Re-added c receives a new tail position and is the next successor.

Constraints
1 <= operations.length <= 10^5.
Each operation is exactly ADD, REMOVE, or NEXT with the stated arity.
Each movie ID contains between 1 and 64 printable ASCII characters and is not NONE.
The operation sequence is evaluated by one thread.

Reported by candidates. Source: FastPrep

Pattern and pitfall

The trick is separating identity from position. Keep a position-to-movie ordered map and a movie-to-position map. Every successful ADD gets a fresh, ever-increasing position, and REMOVE deletes from both maps. The cursor stores the last displayed position number, not a movie ID. NEXT finds the smallest active position strictly greater than the cursor. If none exists, it wraps to the smallest active position. If the map is empty, it returns NONE and leaves the cursor alone. The pitfall is moving the cursor on an empty NEXT, or reusing positions so a re-added movie jumps back to its old slot. Example 1 shows it: after B is removed and re-added, it lands after C. You need an ordered structure with a successor lookup, like a TreeMap or a sorted container, giving O(log n) per operation. A plain hash map won't give you the successor. If the live OA freezes you on this, StealthCoder can hand you the structure fast.

If you see this problem in your OA tomorrow, the play is to recognize the pattern in 30 seconds. StealthCoder buys you that recognition.

If this hits your live OA

You can drill Movie Billboard Rotation cold, or you can hedge it. StealthCoder runs invisibly during screen share and surfaces a working solution in under 2 seconds. The proctor sees the IDE. They don't see what's behind it. Built by an Amazon engineer who passed his OA cold and still thinks the filter is broken.

Get StealthCoder

Related leaked OAs

⏵ The honest play

You've seen the question. Make sure you actually pass Netflix's OA.

Netflix reuses patterns across OAs. Built by an Amazon engineer who passed his OA cold and still thinks the filter is broken. Works on HackerRank, CodeSignal, CoderPad, and Karat.

Movie Billboard Rotation FAQ

What's the trick in the Netflix Movie Billboard Rotation problem?+

Store the cursor as a position number, not a movie. Positions only increase and are never reused. NEXT asks for the smallest active position greater than the cursor, then wraps to the smallest active one. That one idea handles removals under the cursor and re-adds cleanly.

Why can't I just use a linked list or a queue?+

Removing the node under the cursor leaves you without a place to resume from. A queue also breaks on arbitrary removes. You need ordered positions with a successor lookup, plus a movie-to-position map for O(1) removal. That's exactly what the problem statement tells you to build.

What edge cases break a naive solution?+

Empty rotation returning NONE without moving the cursor. Duplicate ADDs and missing REMOVEs being no-ops. Re-adding a removed movie, which must go to a new tail position. Removing the movie at the cursor, then calling NEXT. Example 3 covers wrap-around after deleting the tail.

What time complexity should I aim for?+

With up to 10^5 operations, each one should be O(log n) or better. An ordered map gives you insert, delete, and successor lookup in O(log n). Scanning forward through deleted positions on every NEXT can degrade to O(n) per call and time out.

How do I prepare for this in 48 hours?+

Write the solution once from scratch in your language's ordered map or sorted set. Then trace Example 1 and Example 3 by hand, watching the cursor value. Check which successor operation your language offers, like higher or upper_bound. If your language lacks one, plan a fallback like a sorted list with bisect.

Problem reported by candidates from a real Online Assessment. Sourced from a publicly-available candidate-aggregated repository. Not affiliated with Netflix.

OA at Netflix?
Invisible during screen share
Get it