Understand
30-second explanation
Build the interview-ready mental model before comparing implementations.
You simulate q operations over n initially-empty sequences while carrying a running `lastAnswer` (starts at 0). For each query, the target sequence index is `(x ^ lastAnswer) % n`. Type 1 appends y to that sequence; type 2 reads element `y % size` of that sequence, sets `lastAnswer` to it, and records it. Keep n separate growable lists so append and indexed read are O(1) — the whole thing runs in O(q).
Interview contextWhat is testedWhere candidates slipHow to stand outExplore interview contextHide interview context
What's being tested
Whether you can read a precise operational spec and reproduce it exactly — correct state carry-over, the XOR-then-mod index, and the right output for only type-2 queries.
Where candidates slip
Forgetting to XOR with lastAnswer (using x % n directly), not initializing lastAnswer to 0, or storing all appends in one flat list and scanning to reconstruct a sequence, turning O(q) into O(q²).
How to stand out
Restate the index formula out loud before coding, and pick a structure (array of lists) that gives O(1) append and read so you can state O(q) confidently.
Choose
Compare the available approaches
Use constraints and trade-offs to select the route you can defend in an interview.
Interactive decision treeInteractiveChoose the right approachFirst decision previewQuery (type, x, y)type?12Explore the full treeCollapse the tree
Learn & trace
Build each solution step by step
Move from the core idea to a visual trace, implementation, proof, and edge cases.
Approach 1 of 2
Baseline — Single Flat Log, Reconstruct on Read
1Hint 1Explore hintHide hint
You could record every append as a (sequenceIndex, value) pair in one list. How would you answer a type-2 read?
2Hint 2Explore hintHide hint
To read element j of sequence idx, you'd filter the log for that idx and then index into the filtered result. What does that filter cost?
3Hint 3Explore hintHide hint
If every type-2 query rescans the full log, how does total time grow with q?
A · Core idea
Store every append as a (idx, value) pair in one global list. To serve a type-2 query, walk that list, collect the values whose idx matches, then index into the collected list with y % size.
Why someone reaches for this. It feels simpler to have one container than to manage n separate ones, and it sidesteps thinking about how to size the per-sequence lists up front.
Why it's quadratic. A type-2 query has to reconstruct the target sequence by filtering the whole log every time — there's no direct handle on 'sequence idx'. With up to q appends and q reads, that's O(q) work per read and O(q²) overall. For q = 10⁵ that's ten billion operations — far too slow.
The fix. The sequences are independent and addressed by index, so give each its own list. Then 'append to sequence idx' and 'read position j of sequence idx' are both direct O(1) operations, no scanning.
B · Visual dry run
Interactive dry run
Select a frame to connect the decision with its visual state.
n = 2, queries = [[1,0,5],[1,1,7],[2,1,0]]Array state
read idx 1
keep entries with idx == 1
[7]C · Code with teaching comments
Reference implementation previewpublic List<Integer> dynamicArray(int n, int[][] queries) { List<int[]> log = new ArrayList<>(); List<Integer> answers = new ArrayList<>(); int lastAnswer = 0; for (int[] q : queries) {Explore the full codeHide the full code
D · Why it works and complexityO(q²) timeO(q) spaceOpen the invariant and proofExplore the proofHide the proof
Whenever you find yourself filtering a flat log to recover a sub-collection on every query, that's the signal to key the data by that sub-collection up front — here, an array of lists indexed directly by sequence number.
ComplexityO(q²) time, O(q) space — Each type-2 read scans the entire append log to gather one sequence's elements: O(q) per read, up to q reads → O(q²).
E · Edge cases and pitfalls5many type-2 queries — Each triggers a full log scan, exposing the O(q²) blowup.Explore edge casesHide edge cases
Edge cases handled
many type-2 queriesEach triggers a full log scan, exposing the O(q²) blowup.n = 1All appends land in one logical sequence; the filter returns everything.
Pitfalls
- Rescanning the log per read — quadratic on large q.
- Forgetting the XOR and using x % n directly.
- Not seeding lastAnswer to 0 before the loop.
Approach 2 of 2 · Optimal
Array of Lists — Direct Simulation (Optimal)
1Hint 1Explore hintHide hint
The sequences are addressed by an integer index. What structure gives O(1) access to the idx-th collection?
2Hint 2Explore hintHide hint
Make an array of n lists. Append pushes to seq[idx]; read indexes into seq[idx] directly.
3Hint 3Explore hintHide hint
Carry lastAnswer across iterations and recompute idx each time as (x XOR lastAnswer) % n.
A · Core idea
Hold n independent growable lists in an array and a single lastAnswer initialized to 0. Process queries one by one, deriving the target index from lastAnswer each time.
Why the index formula is the crux. Every query computes idx = (x ^ lastAnswer) % n. The XOR couples each query to the result of the previous type-2 query, so you can't precompute indices or reorder queries — you must step through them in order, carrying state. Dropping the XOR (using x % n) targets the wrong sequence and produces wrong output that still 'looks plausible', which is why it's such a common silent bug.
Why an array of lists. The sequences are addressed by a small integer idx in [0, n), so an array gives O(1) access to the right list. Appending to a growable list (ArrayList / Python list) is amortized O(1), and reading position y % size is O(1). No scanning, no reconstruction — exactly the cost you'd hope for.
Why `y % size` for reads. The read index y can exceed the current length of the chosen sequence, so it's wrapped with % size. Since the problem guarantees the target sequence is non-empty on a type-2 query, the modulo is always well-defined (no division by zero).
Why only type-2 emits output. Type-1 mutates state silently; type-2 both updates lastAnswer (affecting all future indices) and appends to the answer list. Keeping that distinction straight is the last piece of faithfully reproducing the spec.
B · Visual dry run
Interactive dry run
Select a frame to connect the decision with its visual state.
n = 2, queries = [[1,0,5],[1,1,7],[1,0,3],[2,1,0],[2,1,1]]Array state
seq0
holds [5, 3]
[7, 3]C · Code with teaching comments
D · Why it works and complexityO(q) timeO(n + total appends) spaceOpen the invariant and proofExplore the proofHide the proof
There's no asymptotic cleverness to chase here — the win is choosing the data structure that matches how the data is addressed. 'Indexed by a small integer' ⇒ array; 'grows over time' ⇒ growable list. Match the structure to the access pattern and the O(q) bound falls out.
ComplexityO(q) time, O(n + total appends) space — Each query does O(1) work: one index computation, then either an amortized-O(1) append or an O(1) positional read. Across q queries that's O(q). Space is O(n) for the outer array plus the total number of appended elements.
E · Edge cases and pitfalls5n = 1 — idx is always 0; all appends and reads hit the single sequence.Explore edge casesHide edge cases
Edge cases handled
n = 1idx is always 0; all appends and reads hit the single sequence.y larger than sequence lengthy % size wraps it into a valid position.
Pitfalls
- Initializing the lists with [[]] * n in Python — that aliases one shared list across all indices.
- Using x % n instead of (x ^ lastAnswer) % n.
- Forgetting to update lastAnswer on type-2, breaking every later index.
Practice
Try the solution yourself
Edit the optimal implementation, test another input, and observe the result.
Editable code previewpublic List<Integer> dynamicArray(int n, int[][] queries) { List<List<Integer>> seq = new ArrayList<>(); for (int i = 0; i < n; i++) { seq.add(new ArrayList<>()); }Explore the playgroundClose the playground
Avoid mistakes
Recognize the interview traps
Understand why common attempts fail before reviewing the corrected implementation.
1Dropping the XOR
The index must couple to the previous answer; using x alone targets the wrong sequence and silently produces wrong output.
Explore the code comparisonHide the code comparison
Dropping the XOR
The index must couple to the previous answer; using x alone targets the wrong sequence and silently produces wrong output.
Don't write this
int idx = q[1] % n;Write this instead
int idx = (q[1] ^ lastAnswer) % n;2Aliased sequences in Python
[[]] * n creates n references to the SAME inner list, so an append to one shows up in all of them.
Explore the code comparisonHide the code comparison
Aliased sequences in Python
[[]] * n creates n references to the SAME inner list, so an append to one shows up in all of them.
Don't write this
seq = [[]] * nWrite this instead
seq = [[] for _ in range(n)]3Stale lastAnswer
If a type-2 query reads the value but doesn't update lastAnswer, every subsequent index is computed from the wrong base.
Explore the code comparisonHide the code comparison
Stale lastAnswer
If a type-2 query reads the value but doesn't update lastAnswer, every subsequent index is computed from the wrong base.
Don't write this
answers.append(target[y % len(target)])Write this instead
last_answer = target[y % len(target)]
answers.append(last_answer)Revise
Carry the pattern into the interview
Pattern to remember
Stateful simulation with a carried lastAnswer index
Code pattern to memorize
idx = (x ^ lastAnswer) % n
type 1: seq[idx].append(y)
type 2: lastAnswer = seq[idx][y % len(seq[idx])]; record lastAnswerRules to remember
- 1Initialize
lastAnswer = 0before the first query — it seeds the very first index computation. - 2The target index is
(x XOR lastAnswer) % n, not justx % n— the XOR with the previous answer is the whole gimmick. - 3Type-2 reads use
y % size(target), wrapping the index into the chosen sequence's current length. - 4Keep
nseparate lists so append is amortized O(1) and indexed read is O(1) — don't store everything in one flat log. - 5Only type-2 queries produce output; type-1 queries silently mutate state.
Use this pattern when
- A problem describes an exact procedure and asks you to reproduce its outputs
- Operations carry forward state (here, lastAnswer) that affects later steps
- You need O(1) append and O(1) positional read on several growing collections
Choose another pattern when
- There's a closed-form or pattern you can derive instead of stepping through every op
- State doesn't carry between operations → each query is independent and you can batch
- You need range queries over the sequences → a segment tree / Fenwick, not plain lists
Interview takeaway
Simulation problems are graded on faithfully translating the spec, not on cleverness. The two traps here are seeding `lastAnswer = 0` and computing the index as `(x ^ lastAnswer) % n` — get those right and the rest is O(1) list operations.
Continue
Transfer the pattern to another problem
Use a direct variation or pattern sibling to prove the idea is reusable.
Transferable patternStateful simulation. Faithfully reproduce the spec's procedure, carrying lastAnswer between steps and matching the data structure (array of lists) to the access pattern (index-addressed, append-grown). The output bound O(q) follows from O(1) append and read.
Practice queueDirect variations and pattern siblings
Direct follow-ups