โ† Back to All Algorithms

Medium Interview Frequency: โญโญโญ

Valid Sudoku

Determine if a partially filled 9x9 Sudoku board is valid according to row, column, and 3x3 sub-box constraints.

Hash Set Matrix Validation Constraints

๐Ÿ“š Table of Contents

  1. Problem Statement
  2. Real-World Analogy
  3. Key Insights
  4. Solution Approaches
  5. Step-by-Step Walkthrough
  6. Complexity Analysis
  7. Edge Cases
  8. Test Cases
  9. Interview Tips
  10. Related Problems
  11. Key Takeaways

๐Ÿ“‹ Problem Statement

Given a 9x9 board with digits 1-9 and . placeholders, validate that no row, column, or 3x3 sub-box contains duplicate digits.

Example (Valid)

[["5","3",".",".","7",".",".",".","."], ...]

No conflicts in any row, column, or box.

๐ŸŽฏ Real-World Analogy

Conference Seating Rules

Think of each number as a speaker ID. No speaker can appear twice in the same row section, same column track, or same breakout room (3x3 box).

๐Ÿ’ก Key Insights

๐Ÿ’ป Solution Approaches

Approach 1: Separate Passes per Row/Column/Box

Time: O(81) | Space: O(9)

Works, but involves repetitive loops and duplicated logic.

Approach 2: Single Pass with 3 Hash Sets (Recommended)

Time: O(81) | Space: O(81)

In practice this is constant for fixed 9x9 boards; in generalized NxN notation it's O(Nยฒ).

Python Implementation

from typing import List def is_valid_sudoku(board: List[List[str]]) -> bool: rows = set() cols = set() boxes = set() for r in range(9): for c in range(9): value = board[r][c] if value == '.': continue row_key = (r, value) col_key = (c, value) box_key = (r // 3, c // 3, value) if row_key in rows or col_key in cols or box_key in boxes: return False rows.add(row_key) cols.add(col_key) boxes.add(box_key) return True

JavaScript Implementation

function isValidSudoku(board) { const rows = new Set(); const cols = new Set(); const boxes = new Set(); for (let r = 0; r < 9; r += 1) { for (let c = 0; c < 9; c += 1) { const value = board[r][c]; if (value === '.') continue; const rowKey = `${r}-${value}`; const colKey = `${c}-${value}`; const boxKey = `${Math.floor(r / 3)}-${Math.floor(c / 3)}-${value}`; if (rows.has(rowKey) || cols.has(colKey) || boxes.has(boxKey)) { return false; } rows.add(rowKey); cols.add(colKey); boxes.add(boxKey); } } return true; }

๐Ÿ” Step-by-Step Walkthrough

Suppose we read cell (0,0)='5'. We add (0,'5'), (0,'5') for column, and (0,0,'5') for box.

Later if another '5' appears in row 0, the row key already exists and we immediately return false.

โšก Complexity Analysis

Time: O(81) for fixed Sudoku size, or O(Nยฒ) for generalized board sizes.

Space: O(81) for stored seen entries (constant in 9x9 case).

๐Ÿ”ง Edge Cases

๐Ÿงช Test Cases

Python

def test_is_valid_sudoku(): valid_board = [ ["5","3",".",".","7",".",".",".","."], ["6",".",".","1","9","5",".",".","."], [".","9","8",".",".",".",".","6","."], ["8",".",".",".","6",".",".",".","3"], ["4",".",".","8",".","3",".",".","1"], ["7",".",".",".","2",".",".",".","6"], [".","6",".",".",".",".","2","8","."], [".",".",".","4","1","9",".",".","5"], [".",".",".",".","8",".",".","7","9"], ] invalid_row = [row[:] for row in valid_board] invalid_row[0][2] = "5" assert is_valid_sudoku(valid_board) is True assert is_valid_sudoku(invalid_row) is False print("all tests passed")

JavaScript

function testIsValidSudoku() { const validBoard = [ ["5","3",".",".","7",".",".",".","."], ["6",".",".","1","9","5",".",".","."], [".","9","8",".",".",".",".","6","."], ["8",".",".",".","6",".",".",".","3"], ["4",".",".","8",".","3",".",".","1"], ["7",".",".",".","2",".",".",".","6"], [".","6",".",".",".",".","2","8","."], [".",".",".","4","1","9",".",".","5"], [".",".",".",".","8",".",".","7","9"], ]; const invalidBoard = validBoard.map((row) => [...row]); invalidBoard[0][2] = "5"; console.assert(isValidSudoku(validBoard) === true, "valid board"); console.assert(isValidSudoku(invalidBoard) === false, "invalid row duplicate"); console.log("all tests passed"); }

๐Ÿ’ผ Interview Tips

๐ŸŽ“ Key Takeaways

โ† Back to All Algorithms