Understand
30-second explanation
Build the interview-ready mental model before comparing implementations.
Validate that no digit repeats within any row, column, or 3×3 box — partial boards are fine, only filled cells matter. Make one pass over the 81 cells, maintaining a seen-set per row, per column, and per box; the box index is (r/3)*3 + (c/3). If a digit is already in its row/col/box set, it's invalid. O(1) time and space because the board is fixed at 9×9.
Interview contextWhat is testedWhere candidates slipHow to stand outExplore interview contextHide interview context
What's being tested
Whether you can track three overlapping uniqueness constraints in one pass and derive the 3×3 box index correctly — and whether you realize you only check, not solve.
Where candidates slip
Botching the box index formula, or treating empty cells as conflicts. Some also try to solve the puzzle when only validation is asked.
How to stand out
Use a single pass updating all three sets together, justify the O(1) bound from the fixed 9×9 size, and encode the box key cleanly.
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 previewVisit cell (r,c)Empty '.'?YesNoExplore the full treeCollapse the tree
How to read it:Each filled cell checks/updates its row set, column set, and 3×3 box set.
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
Three Separate Scans
1Hint 1Explore hintHide hint
The rules name three checks: rows, columns, boxes. What if you validate each independently?
2Hint 2Explore hintHide hint
Scan all rows for duplicates, then all columns, then all nine boxes — a fresh set per group.
3Hint 3Explore hintHide hint
Correct, but three passes over the board. You can fold them into a single pass.
A · Core idea
Validate each rule in its own sweep. First, for each of the 9 rows, use a set to detect a repeated digit. Then do the same for each of the 9 columns. Finally, for each of the 9 boxes, gather its cells and check for repeats. If any sweep finds a duplicate, return false; otherwise true.
Why mention it. It maps one-to-one onto the three stated rules, so it's easy to reason about and verify. The downside is three traversals and slightly more bookkeeping — the single-pass version checks all three groups per cell instead.
B · Visual dry run
Interactive dry run
Select a frame to connect the decision with its visual state.
Top-left box has two 5srow scan
no row repeats
okfalseC · Code with teaching comments
Reference implementation previewpublic boolean isValidSudoku(char[][] board) { for (int r = 0; r < 9; r++) { Set<Character> seen = new HashSet<>(); for (int c = 0; c < 9; c++) if (board[r][c] != '.' && !seen.add(board[r][c])) return false;Explore the full codeHide the full code
D · Why it works and complexityO(1) timeO(1) spaceOpen the invariant and proofExplore the proofHide the proof
Each rule is just 'no duplicates within this grouping' — the same Contains Duplicate check applied to rows, columns, and boxes. Recognizing that lets you merge the sweeps.
ComplexityO(1) time, O(1) space — All scans cover a fixed 81-cell board, so everything is O(1) for the standard 9×9 size.
E · Edge cases and pitfalls2Treating '.' as a digit and reporting false conflicts.Explore edge casesHide edge cases
Pitfalls
- Treating '.' as a digit and reporting false conflicts.
- Wrong box-corner math (box // 3 vs box % 3 swapped).
Approach 2 of 2 · Optimal
Single Pass — Row/Col/Box Sets (Optimal)
1Hint 1Explore hintHide hint
Can you check the row, column, and box constraints for a cell all at once, in a single visit?
2Hint 2Explore hintHide hint
Keep 9 row sets, 9 column sets, and 9 box sets. For each filled cell, check and update all three.
3Hint 3Explore hintHide hint
Compute the box index as (r // 3) * 3 + (c // 3). One pass over 81 cells does it.
A · Core idea
Maintain three arrays of sets: rows[9], cols[9], and boxes[9]. Walk every cell (r, c). Skip empties. For a filled digit d, compute the box index b = (r // 3) * 3 + (c // 3). If d already appears in rows[r], cols[c], or boxes[b], the board is invalid — return false. Otherwise insert d into all three sets and continue. If the pass completes with no conflict, return true.
The box index formula. Integer-dividing the row and column by 3 collapses each coordinate to its band (0, 1, or 2). (r // 3) picks the horizontal band of boxes (0, 3, or 6 after ×3) and (c // 3) picks the column within that band, giving a unique box id 0–8. Cells (0,0) and (2,2) both map to box 0; (0,3) maps to box 1; and so on.
B · Visual dry run
Interactive dry run
Select a frame to connect the decision with its visual state.
Cells (0,0)=5, (0,1)=3, (1,0)=5Array state
c=0,1,2
→ box 0
falseC · Code with teaching comments
D · Why it works and complexityO(1) timeO(1) spaceOpen the invariant and proofExplore the proofHide the proof
It's Contains Duplicate run in parallel across three partitions of the same cell. The only real insight is encoding the box membership; once a cell knows which box it's in, the duplicate check is identical to the row and column checks.
ComplexityO(1) time, O(1) space — One pass over the fixed 81 cells with O(1) set operations and 27 fixed-size sets → O(1) time and space for the 9×9 board.
E · Edge cases and pitfalls5Completely empty board (all '.') — No filled cells, no conflicts → true.Explore edge casesHide edge cases
Edge cases handled
Completely empty board (all '.')No filled cells, no conflicts → true.Duplicate only within a box (rows/cols clean)boxes[b].add returns false → correctly invalid.
Pitfalls
- Box index as (r % 3) * 3 + c % 3 — that groups the wrong cells; use integer division.
- Sharing one set across rows/cols/boxes — they must be independent.
- Inserting before checking — a digit would 'conflict with itself'.
Practice
Try the solution yourself
Edit the optimal implementation, test another input, and observe the result.
Editable code previewpublic boolean isValidSudoku(char[][] board) { Set<Character>[] rows = new HashSet[9]; Set<Character>[] cols = new HashSet[9]; Set<Character>[] boxes = new HashSet[9]; for (int i = 0; i < 9; i++) {Explore the playgroundClose the playground
Avoid mistakes
Recognize the interview traps
Understand why common attempts fail before reviewing the corrected implementation.
1Incorrect box index
The box id must be (row // 3) * 3 + (col // 3). Using modulo on the row/col instead of integer division groups non-adjacent cells and mis-validates.
Explore the code comparisonHide the code comparison
Incorrect box index
The box id must be (row // 3) * 3 + (col // 3). Using modulo on the row/col instead of integer division groups non-adjacent cells and mis-validates.
Don't write this
b = (r % 3) * 3 + (c % 3) # groups the wrong cellsWrite this instead
b = (r // 3) * 3 + (c // 3)2Counting empty cells
'.' marks an empty cell and must be skipped; adding it to the sets makes multiple empties look like a duplicate.
Explore the code comparisonHide the code comparison
Counting empty cells
'.' marks an empty cell and must be skipped; adding it to the sets makes multiple empties look like a duplicate.
Don't write this
if (!rows[r].add(d)) return false; // runs even when d == '.'Write this instead
if (d == '.') continue;
if (!rows[r].add(d)) return false;Revise
Carry the pattern into the interview
Pattern to remember
Constraint tracking with sets (row / col / box)
Code pattern to memorize
rows, cols, boxes = [set() for _ in range(9)] ×3
for r in 0..8, c in 0..8:
d = board[r][c]; if d == '.': continue
b = (r//3)*3 + c//3
if d in rows[r] or d in cols[c] or d in boxes[b]: return False
add d to all threeRules to remember
- 1Only validate filled cells — '.' (empty) never causes a conflict.
- 2Three independent constraint groups: 9 rows, 9 cols, 9 boxes.
- 3Box index =
(row // 3) * 3 + (col // 3)— memorize this mapping. - 4Check membership in all three sets before inserting the digit.
- 5You are NOT solving the puzzle — only checking the current board doesn't violate the rules.
Use this pattern when
- Grid problems with row/column/region uniqueness constraints
- Detecting duplicates within multiple overlapping groupings at once
- Any 'no repeats per partition' validation
Choose another pattern when
- Need to actually fill the board → backtracking (Sudoku Solver)
- Single 1-D uniqueness → one set suffices (Contains Duplicate)
- Region isn't a clean fixed tiling → recompute grouping logic carefully
Interview takeaway
The whole problem is duplicate detection replicated across three groupings simultaneously. The box-index formula is the only non-obvious piece; everything else is hash-set membership.
Continue
Transfer the pattern to another problem
Use a direct variation or pattern sibling to prove the idea is reusable.
Transferable patternMulti-constraint duplicate detection with sets. Reach for it on grid problems with row/column/region uniqueness rules. The constraint sets carry straight over to backtracking-based Sudoku Solver.
Practice queueDirect variations and pattern siblings
Direct follow-ups
- Sudoku SolverComing soonNow actually fill the board — backtracking with the same constraint sets.
- Contains DuplicateThe 1-D version of the per-group duplicate check used here.
- Set Matrix ZeroesComing soonAnother grid problem driven by row/column bookkeeping.