Skip to content

272. Sudoku Solver

๐Ÿ”— LeetCode Problem: 37. Sudoku Solver
๐Ÿ“Š Difficulty: Hard
๐Ÿท๏ธ Topics: Array, Backtracking, Matrix

Problem Statement

Write a program to solve a Sudoku puzzle by filling the empty cells.

A sudoku solution must satisfy all of the following rules:

  1. Each of the digits 1-9 must occur exactly once in each row.
  2. Each of the digits 1-9 must occur exactly once in each column.
  3. Each of the digits 1-9 must occur exactly once in each of the 9 3x3 sub-boxes of the grid.

The '.' character indicates empty cells.

Example 1:

Input: 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"]]

Output:
[["5","3","4","6","7","8","9","1","2"],
 ["6","7","2","1","9","5","3","4","8"],
 ["1","9","8","3","4","2","5","6","7"],
 ["8","5","9","7","6","1","4","2","3"],
 ["4","2","6","8","5","3","7","9","1"],
 ["7","1","3","9","2","4","8","5","6"],
 ["9","6","1","5","3","7","2","8","4"],
 ["2","8","7","4","1","9","6","3","5"],
 ["3","4","5","2","8","6","1","7","9"]]

Constraints: - board.length == 9 - board[i].length == 9 - board[i][j] is a digit 1-9 or '.' - It is guaranteed that the input board has only one solution.


๐ŸŒŸ ELI5: The Simple Idea!

Think of filling a Sudoku puzzle step by step:

You have a 9ร—9 grid with some numbers filled in.
You need to fill the empty cells (marked with '.').

Rules:
1. Each row must have 1-9 (no repeats)
2. Each column must have 1-9 (no repeats)
3. Each 3ร—3 box must have 1-9 (no repeats)

Strategy:
1. Find an empty cell
2. Try placing 1, 2, 3, ... 9
3. For each number, check if it's valid (doesn't violate rules)
4. If valid, place it and move to next empty cell
5. If stuck (no valid number), BACKTRACK - undo and try different number
6. Repeat until board is complete!

Example - Filling one cell:

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

Empty cell at (0,2):
  Try 1? Check row 0: has 5,3,7 โ†’ 1 valid โœ“
        Check col 2: has 8 โ†’ 1 valid โœ“
        Check box 0: has 5,3,6,9,8 โ†’ 1 valid โœ“
        Place 1? Try it, move forward!

  If later we get stuck:
    Backtrack, remove 1, try 2, 3, ... etc.

๐ŸŽจ Visual Understanding

The 9ร—9 Grid Structure

Grid indices (row, col):
     0   1   2   3   4   5   6   7   8
0   [5] [3] [.] [.] [7] [.] [.] [.] [.]
1   [6] [.] [.] [1] [9] [5] [.] [.] [.]
2   [.] [9] [8] [.] [.] [.] [.] [6] [.]
3   [8] [.] [.] [.] [6] [.] [.] [.] [3]
4   [4] [.] [.] [8] [.] [3] [.] [.] [1]
5   [7] [.] [.] [.] [2] [.] [.] [.] [6]
6   [.] [6] [.] [.] [.] [.] [2] [8] [.]
7   [.] [.] [.] [4] [1] [9] [.] [.] [5]
8   [.] [.] [.] [.] [8] [.] [.] [7] [9]

The 9 Sub-Boxes (3ร—3 each)

Box numbering:
  Box 0 | Box 1 | Box 2
  ------+-------+------
  Box 3 | Box 4 | Box 5
  ------+-------+------
  Box 6 | Box 7 | Box 8

Box 0 (top-left):        Box 4 (center):
  5 3 .                    8 . 3
  6 . .                    . . .
  . 9 8                    . 2 .

Box index calculation:
  boxIndex = (row / 3) * 3 + (col / 3)

  Example: cell (4,5) โ†’ box = (4/3)*3 + (5/3) = 1*3 + 1 = 4 โœ“

๐ŸŽฏ CRITICAL CONCEPT: Box Starting Position Calculation

This is the MOST CONFUSING part of Sudoku! Let me break it down step by step:

The Grid Layout with Coordinates

The 9ร—9 grid is divided into 9 boxes of 3ร—3:

     Col: 0  1  2 | 3  4  5 | 6  7  8
Row 0:   [0][0][0] [1][1][1] [2][2][2]  โ† Box numbers in each cell
Row 1:   [0][0][0] [1][1][1] [2][2][2]
Row 2:   [0][0][0] [1][1][1] [2][2][2]
     ----+---------+---------+---------
Row 3:   [3][3][3] [4][4][4] [5][5][5]
Row 4:   [3][3][3] [4][4][4] [5][5][5]
Row 5:   [3][3][3] [4][4][4] [5][5][5]
     ----+---------+---------+---------
Row 6:   [6][6][6] [7][7][7] [8][8][8]
Row 7:   [6][6][6] [7][7][7] [8][8][8]
Row 8:   [6][6][6] [7][7][7] [8][8][8]

Notice the pattern:
  Rows 0-2: Boxes 0, 1, 2
  Rows 3-5: Boxes 3, 4, 5
  Rows 6-8: Boxes 6, 7, 8

Understanding the Box Calculation - Step by Step

Question: Given a cell at (row, col), which 3ร—3 box does it belong to?

Example 1: Cell at (4, 5)

Step 1: Which BOX ROW GROUP?
  Row 4 is in which group of 3?

  Rows 0-2: Group 0
  Rows 3-5: Group 1 โ† Row 4 is here!
  Rows 6-8: Group 2

  Formula: row / 3 = 4 / 3 = 1 (integer division)
  โ†’ Box row group = 1

Step 2: Which BOX COLUMN GROUP?
  Col 5 is in which group of 3?

  Cols 0-2: Group 0
  Cols 3-5: Group 1 โ† Col 5 is here!
  Cols 6-8: Group 2

  Formula: col / 3 = 5 / 3 = 1 (integer division)
  โ†’ Box col group = 1

Step 3: What's the STARTING POSITION of this box?
  Box row group 1 starts at row: 1 ร— 3 = 3
  Box col group 1 starts at col: 1 ร— 3 = 3

  โ†’ Box starts at (3, 3)

  The 3ร—3 box is:
       Col: 3  4  5
  Row 3:  [ ][ ][ ]
  Row 4:  [ ][X][ ] โ† Our cell (4,5)
  Row 5:  [ ][ ][ ]

Visual Walkthrough:

Step-by-step for cell (4, 5):

1. row / 3 = 4 / 3 = 1
   "Cell is in box row group 1"

   Visualize:
     Group 0: rows 0,1,2
     Group 1: rows 3,4,5 โ† HERE!
     Group 2: rows 6,7,8

2. col / 3 = 5 / 3 = 1
   "Cell is in box column group 1"

   Visualize:
     Group 0: cols 0,1,2
     Group 1: cols 3,4,5 โ† HERE!
     Group 2: cols 6,7,8

3. Convert group to starting position:
   boxRow = 1 ร— 3 = 3  (group 1 starts at row 3)
   boxCol = 1 ร— 3 = 3  (group 1 starts at col 3)

   Full board visualization:
        0  1  2 | 3  4  5 | 6  7  8
   0   [ ][ ][ ] [ ][ ][ ] [ ][ ][ ]
   1   [ ][ ][ ] [ ][ ][ ] [ ][ ][ ]
   2   [ ][ ][ ] [ ][ ][ ] [ ][ ][ ]
      -----------+---------+---------
   3   [ ][ ][ ] [S][ยท][ยท] [ ][ ][ ]  S = Starting position (3,3)
   4   [ ][ ][ ] [ยท][X][ยท] [ ][ ][ ]  X = Our cell (4,5)
   5   [ ][ ][ ] [ยท][ยท][ยท] [ ][ ][ ]  ยท = Other cells in box
      -----------+---------+---------
   6   [ ][ ][ ] [ ][ ][ ] [ ][ ][ ]
   7   [ ][ ][ ] [ ][ ][ ] [ ][ ][ ]
   8   [ ][ ][ ] [ ][ ][ ] [ ][ ][ ]

4. Loop through the 3ร—3 box:
   for (r = 3; r < 3+3; r++)      // rows 3,4,5
     for (c = 3; c < 3+3; c++)    // cols 3,4,5
       Check board[r][c]

More Examples to Solidify Understanding

Example 2: Cell at (0, 0)

Step 1: row / 3 = 0 / 3 = 0 โ†’ Box row group 0
Step 2: col / 3 = 0 / 3 = 0 โ†’ Box col group 0
Step 3: boxRow = 0 ร— 3 = 0, boxCol = 0 ร— 3 = 0

Starting position: (0, 0)

The box:
     Col: 0  1  2
Row 0:  [X][ ][ ]  โ† Our cell
Row 1:  [ ][ ][ ]
Row 2:  [ ][ ][ ]

Loop: r = 0 to 2, c = 0 to 2 โœ“

Example 3: Cell at (8, 7)

Step 1: row / 3 = 8 / 3 = 2 โ†’ Box row group 2
Step 2: col / 3 = 7 / 3 = 2 โ†’ Box col group 2
Step 3: boxRow = 2 ร— 3 = 6, boxCol = 2 ร— 3 = 6

Starting position: (6, 6)

The box:
     Col: 6  7  8
Row 6:  [ ][ ][ ]
Row 7:  [ ][X][ ]  โ† Our cell (8,7) is in this box
Row 8:  [ ][ ][ ]

Loop: r = 6 to 8, c = 6 to 8 โœ“

Example 4: Cell at (1, 4)

Step 1: row / 3 = 1 / 3 = 0 โ†’ Box row group 0
Step 2: col / 3 = 4 / 3 = 1 โ†’ Box col group 1
Step 3: boxRow = 0 ร— 3 = 0, boxCol = 1 ร— 3 = 3

Starting position: (0, 3)

The box:
     Col: 3  4  5
Row 0:  [ ][ ][ ]
Row 1:  [ ][X][ ]  โ† Our cell
Row 2:  [ ][ ][ ]

Loop: r = 0 to 2, c = 3 to 5 โœ“

Why This Formula Works - The Pattern

The KEY insight:

1. Division by 3 tells us WHICH group (0, 1, or 2)
   row / 3 โ†’ which horizontal band of boxes
   col / 3 โ†’ which vertical band of boxes

2. Multiply by 3 to get STARTING index
   group 0 โ†’ starts at 0
   group 1 โ†’ starts at 3
   group 2 โ†’ starts at 6

   Pattern: group ร— 3 = starting index

3. Then loop +3 from starting position
   Starting at 0 โ†’ check 0,1,2
   Starting at 3 โ†’ check 3,4,5
   Starting at 6 โ†’ check 6,7,8

Visual Pattern:
  Group 0: 0 ร— 3 = 0 โ†’ check indices 0,1,2
  Group 1: 1 ร— 3 = 3 โ†’ check indices 3,4,5
  Group 2: 2 ร— 3 = 6 โ†’ check indices 6,7,8

Common Confusion - Why NOT Just row/3 and col/3?

โŒ WRONG: Why can't we just use row/3 and col/3 directly?

If cell is at (4, 5):
  row / 3 = 1
  col / 3 = 1

  If we loop: for (r = 1; r < 1+3; r++)
              โ†’ r goes from 1 to 3 (checks rows 1,2,3)

  But cell (4,5) is in rows 3,4,5! โœ—

  We'd be checking the WRONG box!

โœ“ CORRECT: Multiply by 3 first!
  boxRow = (row / 3) ร— 3 = 1 ร— 3 = 3
  boxCol = (col / 3) ร— 3 = 1 ร— 3 = 3

  Loop: for (r = 3; r < 3+3; r++)
        โ†’ r goes from 3 to 5 (checks rows 3,4,5) โœ“

  Now checking the CORRECT box!

Memory Aid - The "Divide, Multiply, Add" Pattern

Think of it as a 3-step process:

1. DIVIDE by 3: Find which group (0, 1, or 2)
   row / 3 = which box row group
   col / 3 = which box col group

2. MULTIPLY by 3: Convert group to starting index
   (row / 3) ร— 3 = starting row of box
   (col / 3) ร— 3 = starting col of box

3. ADD 3: Loop through 3ร—3 box
   for (r = start; r < start + 3; r++)
   for (c = start; c < start + 3; c++)

Mnemonic: "Divide to find, Multiply to start, Add to finish!"

Complete Visual Example

Cell at (7, 2) - Where is its 3ร—3 box?

Full board:
     Col: 0  1  2 | 3  4  5 | 6  7  8
Row 0:  [ ][ ][ ] [ ][ ][ ] [ ][ ][ ]
Row 1:  [ ][ ][ ] [ ][ ][ ] [ ][ ][ ]
Row 2:  [ ][ ][ ] [ ][ ][ ] [ ][ ][ ]
    ----+---------+---------+---------
Row 3:  [ ][ ][ ] [ ][ ][ ] [ ][ ][ ]
Row 4:  [ ][ ][ ] [ ][ ][ ] [ ][ ][ ]
Row 5:  [ ][ ][ ] [ ][ ][ ] [ ][ ][ ]
    ----+---------+---------+---------
Row 6:  [S][ยท][ยท] [ ][ ][ ] [ ][ ][ ]  โ† Box starts here
Row 7:  [ยท][ยท][X] [ ][ ][ ] [ ][ ][ ]  โ† Our cell
Row 8:  [ยท][ยท][ยท] [ ][ ][ ] [ ][ ][ ]

Calculation:
  row / 3 = 7 / 3 = 2  (group 2)
  col / 3 = 2 / 3 = 0  (group 0)

  boxRow = 2 ร— 3 = 6
  boxCol = 0 ร— 3 = 0

  Loop: r from 6 to 8, c from 0 to 2

  Checks box in bottom-left corner! โœ“

Constraint Checking Visual

When placing '4' at cell (0,2):

ROW CHECK (row 0):
  [5][3][4][ ][ ][ ][ ][ ][ ]
   โ†‘  โ†‘  โ†‘
  Check: Does row 0 already have 4?
  5, 3 โ†’ No 4 found โœ“

COLUMN CHECK (col 2):
  [4] (0,2) โ† Placing here
  [ ] (1,2)
  [8] (2,2)
  [ ] (3,2)
  [ ] (4,2)
  [ ] (5,2)
  [ ] (6,2)
  [ ] (7,2)
  [ ] (8,2)
  Check: Does col 2 already have 4?
  Only 8 โ†’ No 4 found โœ“

BOX CHECK (box 0):
  5 3 4 โ† Placing here
  6 . .
  . 9 8
  Check: Does box 0 already have 4?
  5,3,6,9,8 โ†’ No 4 found โœ“

All checks pass โ†’ 4 is VALID! โœ“

๐ŸŽจ How Tracking Works - Visual Step by Step

Complete State Tracking - Simplified Example

Simplified 4ร—4 Sudoku for clarity (same logic applies to 9ร—9):

Initial Board:
  1 . | . 4
  . 3 | 4 .
  ----+----
  . 4 | 2 .
  4 . | . 1

Goal: Fill all '.' cells

โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
STEP 1: Find first empty cell (0,1)
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

Board state:
  1 [?] | . 4
  . 3   | 4 .
  -----+-----
  . 4   | 2 .
  4 .   | . 1

Position: (0,1)
Try values: 1, 2, 3, 4

Try 1:
  Row 0 check: has 1 โœ— (invalid)

Try 2:
  Row 0 check: no 2 โœ“
  Col 1 check: no 2 โœ“
  Box 0 check: no 2 โœ“
  โ†’ Place 2! โœ“

Board after placing 2:
  1 [2] | . 4
  . 3   | 4 .
  -----+-----
  . 4   | 2 .
  4 .   | . 1

Move to next empty cell!

โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
STEP 2: Next empty cell (0,2)
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

Board state:
  1 2 | [?] 4
  . 3 | 4   .
  ----+------
  . 4 | 2   .
  4 . | .   1

Position: (0,2)
Try values: 1, 2, 3, 4

Try 1:
  Row 0: has 1 โœ—

Try 2:
  Row 0: has 2 โœ—

Try 3:
  Row 0: no 3 โœ“
  Col 2: no 3 โœ“
  Box 1: has 4, checking 3... no 3 โœ“
  โ†’ Place 3! โœ“

Board after placing 3:
  1 2 | [3] 4
  . 3 | 4   .
  ----+------
  . 4 | 2   .
  4 . | .   1

Continue...

โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
EXAMPLE OF BACKTRACKING - When Stuck
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

Suppose we reach this state:
  1 2 | 3 4
  2 3 | 4 1
  ----+----
  3 4 | 2 [?]
  4 1 | . 2

Position: (2,3)
Try values: 1, 2, 3, 4

Try 1:
  Row 2: no 1 โœ“
  Col 3: has 4,1,2 โ†’ no 1... wait, check again
  Col 3: 4,1,?,2 โ†’ has 1 โœ—

Try 2:
  Row 2: has 2 โœ—

Try 3:
  Row 2: has 3 โœ—

Try 4:
  Row 2: has 4 โœ—

ALL VALUES TRIED, NONE VALID! ๐Ÿ˜ฑ

BACKTRACK! โฌ…๏ธ

Go back to previous cell (2,2)
Remove the value we placed there
Try next value

This is the essence of backtracking!

Real 9ร—9 Tracking - First Few Steps

Initial board (first 3 rows):
     0   1   2 | 3   4   5 | 6   7   8
0   [5] [3] [.] [.] [7] [.] [.] [.] [.]
1   [6] [.] [.] [1] [9] [5] [.] [.] [.]
2   [.] [9] [8] [.] [.] [.] [.] [6] [.]

โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
Cell (0,2): First empty cell
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

Try 1:
  Row 0: [5,3,_,_,7,_,_,_,_] โ†’ no 1 โœ“
  Col 2: [_,_,8,_,_,_,_,_,_] โ†’ no 1 โœ“
  Box 0: [5,3,_,6,_,_,_,9,8] โ†’ no 1 โœ“
  Valid? Seems OK, but let's check more...

Actually, let me try 4:
  Row 0: [5,3,_,_,7,_,_,_,_] โ†’ no 4 โœ“
  Col 2: [_,_,8,_,_,_,_,_,_] โ†’ no 4 โœ“
  Box 0: [5,3,_,6,_,_,_,9,8] โ†’ no 4 โœ“
  Valid? YES โœ“

Place 4:
  Board:
     0   1   2 | 3   4   5 | 6   7   8
0   [5] [3] [4] [.] [7] [.] [.] [.] [.]
1   [6] [.] [.] [1] [9] [5] [.] [.] [.]
2   [.] [9] [8] [.] [.] [.] [.] [6] [.]

โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
Cell (0,3): Next empty cell
โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•

Try 1:
  Row 0: [5,3,4,_,7,_,_,_,_] โ†’ no 1 โœ“
  Col 3: [_,1,_,_,8,_,_,4,_] โ†’ has 1 โœ—
  Invalid!

Try 2:
  Row 0: [5,3,4,_,7,_,_,_,_] โ†’ no 2 โœ“
  Col 3: [_,1,_,_,8,_,_,4,_] โ†’ no 2 โœ“
  Box 1: [_,7,_,1,9,5,_,_,_] โ†’ no 2 โœ“
  Valid? YES โœ“

Place 2:
  Board:
     0   1   2 | 3   4   5 | 6   7   8
0   [5] [3] [4] [2] [7] [.] [.] [.] [.]
1   [6] [.] [.] [1] [9] [5] [.] [.] [.]
2   [.] [9] [8] [.] [.] [.] [.] [6] [.]

... and so on until all cells filled!

Backtracking in Action

Suppose at some point we have:
  Board state with cell (5,7) being filled

Try 1: Invalid (row conflict)
Try 2: Invalid (col conflict)
Try 3: Invalid (box conflict)
Try 4: Invalid (row conflict)
Try 5: Invalid (col conflict)
Try 6: Invalid (box conflict)
Try 7: Invalid (row conflict)
Try 8: Invalid (col conflict)
Try 9: Invalid (box conflict)

ALL 9 VALUES FAILED! ๐Ÿ˜ฑ

BACKTRACK STEPS:
  1. Mark cell (5,7) as empty again: board[5][7] = '.'
  2. Return false to caller
  3. Caller is working on cell (5,6)
  4. Caller tries next value at (5,6)
  5. If all values at (5,6) fail, backtrack further!

Backtracking chain:
  Cell (5,7) fails โ†’ Backtrack to (5,6)
  Cell (5,6) exhausted โ†’ Backtrack to (5,5)
  Cell (5,5) tries next value โ†’ Move forward again

Keep backtracking until find valid path!

Visual Flow Chart

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Start: Find next empty cell            โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
               โ”‚
               โ†“
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Found empty cell?                        โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ NO           โ”‚ YES                       โ”‚
โ”‚ โ†’ SOLVED! โœ“  โ”‚ โ†’ Try values 1-9          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                           โ”‚
                           โ†“
            โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
            โ”‚ For value = 1 to 9:          โ”‚
            โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                           โ”‚
                           โ†“
            โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
            โ”‚ Is value valid?              โ”‚
            โ”‚ (Check row, col, box)        โ”‚
            โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
            โ”‚ NO           โ”‚ YES           โ”‚
            โ”‚ โ†’ Try next   โ”‚ โ†’ Place value โ”‚
            โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                   โ”‚
                                   โ†“
                        โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                        โ”‚ Recurse to next  โ”‚
                        โ”‚ empty cell       โ”‚
                        โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
                        โ”‚ Success โ”‚ Failed โ”‚
                        โ”‚ โ†’ Done! โ”‚ โ†’ Undo โ”‚
                        โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”˜
                                       โ”‚
                                       โ†“
                            โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                            โ”‚ BACKTRACK:   โ”‚
                            โ”‚ Remove value โ”‚
                            โ”‚ Try next     โ”‚
                            โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐ŸŽจ Understanding Box Calculation - The Tricky Part!

Why Box Calculation is Confusing

The formula: boxRow = (row / 3) * 3

What does this even mean? ๐Ÿค”

Let's break it down step by step!

Visual Understanding - The 9 Boxes

The 9ร—9 Sudoku board is divided into 9 boxes (3ร—3 each):

     Columns: 0  1  2 | 3  4  5 | 6  7  8
Rows:
  0          โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
  1          โ”‚ Box 0  โ”‚ Box 1  โ”‚ Box 2  โ”‚
  2          โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
  3          โ”‚ Box 3  โ”‚ Box 4  โ”‚ Box 5  โ”‚
  4          โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
  5          โ”‚ Box 6  โ”‚ Box 7  โ”‚ Box 8  โ”‚
  6          โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  7
  8

Box boundaries:
  Box 0: rows [0,1,2], cols [0,1,2]
  Box 1: rows [0,1,2], cols [3,4,5]
  Box 2: rows [0,1,2], cols [6,7,8]
  Box 3: rows [3,4,5], cols [0,1,2]
  Box 4: rows [3,4,5], cols [3,4,5]  โ† Center box
  Box 5: rows [3,4,5], cols [6,7,8]
  Box 6: rows [6,7,8], cols [0,1,2]
  Box 7: rows [6,7,8], cols [3,4,5]
  Box 8: rows [6,7,8], cols [6,7,8]

Step-by-Step: Finding Box Start

GOAL: Given any cell (row, col), find the TOP-LEFT corner of its box

Example 1: Cell (4, 5) - Which box? Where does box start?

Step 1: Which BOX ROW GROUP? (0-2, 3-5, or 6-8?)
  row = 4
  row / 3 = 4 / 3 = 1 (integer division)

  Meaning: Row 4 is in BOX ROW GROUP 1

  Box row groups:
    Group 0: rows 0,1,2  (rows 0-2)
    Group 1: rows 3,4,5  (rows 3-5)  โ† Row 4 is here!
    Group 2: rows 6,7,8  (rows 6-8)

Step 2: Where does BOX ROW GROUP 1 START?
  Group 1 starts at row: 1 ร— 3 = 3

  Why multiply by 3?
    Group 0 starts at: 0 ร— 3 = 0 โœ“
    Group 1 starts at: 1 ร— 3 = 3 โœ“
    Group 2 starts at: 2 ร— 3 = 6 โœ“

  So: boxRow = (4 / 3) ร— 3 = 1 ร— 3 = 3

Step 3: Which BOX COLUMN GROUP? (0-2, 3-5, or 6-8?)
  col = 5
  col / 3 = 5 / 3 = 1 (integer division)

  Meaning: Col 5 is in BOX COL GROUP 1

  Box col groups:
    Group 0: cols 0,1,2  (cols 0-2)
    Group 1: cols 3,4,5  (cols 3-5)  โ† Col 5 is here!
    Group 2: cols 6,7,8  (cols 6-8)

Step 4: Where does BOX COL GROUP 1 START?
  Group 1 starts at col: 1 ร— 3 = 3

  So: boxCol = (5 / 3) ร— 3 = 1 ร— 3 = 3

RESULT:
  Cell (4, 5) belongs to box starting at (3, 3)
  This is Box 4 (the center box)!

Visual:
     0  1  2 | 3  4  5 | 6  7  8
  0  .  .  . | .  .  . | .  .  .
  1  .  .  . | .  .  . | .  .  .
  2  .  .  . | .  .  . | .  .  .
     --------+---------+--------
  3  .  .  . |โฌ†๏ธ .  . | .  .  .  โ† boxRow = 3
  4  .  .  . | .  X  . | .  .  .  โ† Cell (4,5)
  5  .  .  . | .  .  . | .  .  .
     --------+---------+--------
  6  .  .  . | .  .  . | .  .  .
            โฌ†๏ธ
         boxCol = 3

More Examples with Visuals

Example 2: Cell (0, 0) - Top-left corner

Step 1: row / 3 = 0 / 3 = 0
Step 2: boxRow = 0 ร— 3 = 0
Step 3: col / 3 = 0 / 3 = 0
Step 4: boxCol = 0 ร— 3 = 0

Box starts at: (0, 0) โ† Top-left of Box 0 โœ“

     0  1  2 | 3  4  5 | 6  7  8
  0 โฌ†๏ธ .  . | .  .  . | .  .  .
  1  .  .  . | .  .  . | .  .  .
  2  .  .  . | .  .  . | .  .  .

โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€

Example 3: Cell (8, 8) - Bottom-right corner

Step 1: row / 3 = 8 / 3 = 2
Step 2: boxRow = 2 ร— 3 = 6
Step 3: col / 3 = 8 / 3 = 2
Step 4: boxCol = 2 ร— 3 = 6

Box starts at: (6, 6) โ† Top-left of Box 8 โœ“

     0  1  2 | 3  4  5 | 6  7  8
  6  .  .  . | .  .  . |โฌ†๏ธ .  .
  7  .  .  . | .  .  . | .  .  .
  8  .  .  . | .  .  . | .  .  X  โ† Cell (8,8)

โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€

Example 4: Cell (3, 7) - Middle-right area

Step 1: row / 3 = 3 / 3 = 1
Step 2: boxRow = 1 ร— 3 = 3
Step 3: col / 3 = 7 / 3 = 2
Step 4: boxCol = 2 ร— 3 = 6

Box starts at: (3, 6) โ† Top-left of Box 5 โœ“

     0  1  2 | 3  4  5 | 6  7  8
  3  .  .  . | .  .  . |โฌ†๏ธ X  .  โ† Cell (3,7)
  4  .  .  . | .  .  . | .  .  .
  5  .  .  . | .  .  . | .  .  .

The Pattern - All Possible Starting Positions

There are only 9 possible box starting positions:

Box Row Groups ร— Box Col Groups = 3 ร— 3 = 9 boxes

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Box     โ”‚ Starts at (boxRow, boxCol)      โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Box 0   โ”‚ (0, 0) - top-left               โ”‚
โ”‚ Box 1   โ”‚ (0, 3) - top-center             โ”‚
โ”‚ Box 2   โ”‚ (0, 6) - top-right              โ”‚
โ”‚ Box 3   โ”‚ (3, 0) - middle-left            โ”‚
โ”‚ Box 4   โ”‚ (3, 3) - CENTER                 โ”‚
โ”‚ Box 5   โ”‚ (3, 6) - middle-right           โ”‚
โ”‚ Box 6   โ”‚ (6, 0) - bottom-left            โ”‚
โ”‚ Box 7   โ”‚ (6, 3) - bottom-center          โ”‚
โ”‚ Box 8   โ”‚ (6, 6) - bottom-right           โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Notice the pattern:
  Row starts: 0, 0, 0, 3, 3, 3, 6, 6, 6
  Col starts: 0, 3, 6, 0, 3, 6, 0, 3, 6

  Always multiples of 3!

How the Loop Works

Once we have box starting position (boxRow, boxCol):

for (int r = boxRow; r < boxRow + 3; r++) {
    for (int c = boxCol; c < boxCol + 3; c++) {
        // Check board[r][c]
    }
}

This checks ALL 9 cells in the 3ร—3 box!

Example: Box starting at (3, 3)
  r goes from 3 to 5 (3, 4, 5)
  c goes from 3 to 5 (3, 4, 5)

  Checks cells:
    (3,3) (3,4) (3,5)
    (4,3) (4,4) (4,5)
    (5,3) (5,4) (5,5)

  All 9 cells in Box 4! โœ“

Visual:
     0  1  2 | 3  4  5 | 6  7  8
  3  .  .  . | X  X  X | .  .  .  โ† r=3
  4  .  .  . | X  X  X | .  .  .  โ† r=4
  5  .  .  . | X  X  X | .  .  .  โ† r=5
              โ†‘  โ†‘  โ†‘
           c=3 c=4 c=5

Complete Mental Model

Think of it as:
  "Which 3ร—3 box am I in?" โ†’ Find starting corner โ†’ Check all 9 cells

Division by 3:
  0,1,2 โ†’ 0 (group 0)
  3,4,5 โ†’ 1 (group 1)
  6,7,8 โ†’ 2 (group 2)

Multiply by 3:
  Group 0 โ†’ starts at 0
  Group 1 โ†’ starts at 3
  Group 2 โ†’ starts at 6

Formula compactly expresses:
  "Find which group (0,1,2), then find where that group starts (0,3,6)"

  (row / 3) * 3 = rowGroup ร— 3 = rowGroupStart

Alternative Way to Think About It

Another way to understand the formula:

boxRow = (row / 3) * 3

Can be rewritten as:
  boxRow = row - (row % 3)

Examples:
  row=0: 0 - (0%3) = 0 - 0 = 0 โœ“
  row=1: 1 - (1%3) = 1 - 1 = 0 โœ“
  row=2: 2 - (2%3) = 2 - 2 = 0 โœ“
  row=3: 3 - (3%3) = 3 - 0 = 3 โœ“
  row=4: 4 - (4%3) = 4 - 1 = 3 โœ“
  row=5: 5 - (5%3) = 5 - 2 = 3 โœ“
  row=6: 6 - (6%3) = 6 - 0 = 6 โœ“
  row=7: 7 - (7%3) = 7 - 1 = 6 โœ“
  row=8: 8 - (8%3) = 8 - 2 = 6 โœ“

This "rounds down to nearest multiple of 3"
Which gives us the box starting position!

๐ŸŽฏ Approach: Backtracking โญโญโญ

The Only Solution

Algorithm:

1. Find next empty cell (marked with '.')
2. If no empty cell โ†’ Solved! Return true
3. For each digit 1-9:
   a. Check if digit is valid (row, col, box)
   b. If valid:
      - Place digit
      - Recursively solve rest
      - If solved โ†’ return true
      - Else โ†’ remove digit (backtrack)
4. If all digits 1-9 fail โ†’ return false

Implementation

/**
 * Backtracking solution for Sudoku
 * Time: O(9^(nร—n)) worst case, but pruning makes it much faster
 * Space: O(nร—n) - Recursion depth
 */
class Solution {
    public void solveSudoku(char[][] board) {
        solve(board);
    }

    private boolean solve(char[][] board) {
        // Find next empty cell
        for (int row = 0; row < 9; row++) {
            for (int col = 0; col < 9; col++) {
                if (board[row][col] == '.') {
                    // Try digits 1-9
                    for (char digit = '1'; digit <= '9'; digit++) {
                        if (isValid(board, row, col, digit)) {
                            // Place digit
                            board[row][col] = digit;

                            // Recursively solve rest
                            if (solve(board)) {
                                return true;  // Solved!
                            }

                            // Backtrack - remove digit
                            board[row][col] = '.';
                        }
                    }

                    // All digits 1-9 failed
                    return false;
                }
            }
        }

        // No empty cell found - solved!
        return true;
    }

    private boolean isValid(char[][] board, int row, int col, char digit) {
        // Check row
        for (int c = 0; c < 9; c++) {
            if (board[row][c] == digit) {
                return false;
            }
        }

        // Check column
        for (int r = 0; r < 9; r++) {
            if (board[r][col] == digit) {
                return false;
            }
        }

        // Check 3ร—3 box
        int boxRow = (row / 3) * 3;
        int boxCol = (col / 3) * 3;
        for (int r = boxRow; r < boxRow + 3; r++) {
            for (int c = boxCol; c < boxCol + 3; c++) {
                if (board[r][c] == digit) {
                    return false;
                }
            }
        }

        return true;
    }

    public static void main(String[] args) {
        Solution sol = new Solution();
        char[][] 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'}
        };
        sol.solveSudoku(board);
        // Print solved board
        for (char[] row : board) {
            System.out.println(Arrays.toString(row));
        }
    }
}

โฐ Time: O(9^(nร—n)) worst case, but typically much faster with pruning
๐Ÿ’พ Space: O(nร—n) - Recursion depth (number of empty cells)


๐Ÿ”„ Is Backtracking the Only Way?

Quick Answer: Backtracking is THE Standard Solution

For Sudoku Solver:
  โœ“ Backtracking: Standard, expected, works for all cases
  โœ“ Constraint Propagation: Advanced optimization
  โœ— Brute Force: Too slow (9^81 possibilities!)
  โœ— Dynamic Programming: Not applicable

Bottom Line: Backtracking is the standard solution!

Why Other Approaches Don't Apply

Brute Force (Try All Combinations):

โŒ COMPLETELY IMPRACTICAL

For 9ร—9 Sudoku with ~50 empty cells:
  9^50 = 5 ร— 10^47 combinations!

Even at 1 billion checks per second:
  Would take 10^30 years! ๐Ÿคฏ

Universe age: ~10^10 years

Backtracking prunes early โ†’ Practical!

Dynamic Programming:

โŒ NOT APPLICABLE

Why DP doesn't work:
  1. No optimal substructure
  2. No overlapping subproblems
  3. Constraints are global (entire board)
  4. Each state depends on ALL previous placements

This is a CONSTRAINT SATISFACTION problem,
not an OPTIMIZATION problem.

Advanced: Constraint Propagation:

โœ“ OPTIMIZATION (Not replacement!)

Techniques:
  - Naked Singles: If cell has only one valid digit โ†’ place it
  - Hidden Singles: If digit has only one valid cell in row/col/box โ†’ place it
  - Pointing Pairs: Advanced eliminations

Used in combination with backtracking:
  1. Apply constraint propagation first
  2. Reduces search space
  3. Then use backtracking for remaining cells

Still uses backtracking at core!
Mentioned only for completeness - not expected in interviews!

What Interviewers Expect

Standard Question:
  Interviewer: "Solve this Sudoku"
  Expected: Backtracking with validation

Follow-up Questions:

1. "How do you validate?"
   Answer: "Check row, column, and 3ร—3 box for duplicate"

2. "Can you optimize?"
   Answer: "Yes - instead of finding empty cells during recursion,
            precompute list of empty cells. Saves time."

3. "What's the time complexity?"
   Answer: "Worst case O(9^m) where m = empty cells.
            But pruning makes it much faster in practice."

4. "Is there a better approach?"
   Answer: "For interviews, backtracking is standard.
            Advanced solvers use constraint propagation,
            but that's beyond interview scope."

Interview Strategy

STEP 1: Recognize it's backtracking
  "This is a constraint satisfaction problem.
   I'll use backtracking to try values and backtrack when stuck."

STEP 2: Explain validation
  "For each empty cell, I'll try digits 1-9.
   For each digit, I'll validate:
   - Row doesn't have it
   - Column doesn't have it  
   - 3ร—3 box doesn't have it"

STEP 3: Explain backtracking
  "If valid, place digit and recurse.
   If recursion succeeds, we're done.
   If it fails, remove digit and try next."

STEP 4: Code it up
  - solve() function with backtracking
  - isValid() function for constraint checking

โš ๏ธ Common Mistakes

Mistake 1: Not backtracking (not removing digit)

// โŒ WRONG - Digit stays placed even when path fails!
if (isValid(board, row, col, digit)) {
    board[row][col] = digit;
    if (solve(board)) return true;
    // Forgot to remove!
}

// โœ“ CORRECT - Remove digit after failed attempt
if (isValid(board, row, col, digit)) {
    board[row][col] = digit;
    if (solve(board)) return true;
    board[row][col] = '.';  // Backtrack!
}

Mistake 2: Wrong box calculation

// โŒ WRONG - Incorrect box boundaries
int boxRow = row / 3;
int boxCol = col / 3;
for (int r = boxRow; r < boxRow + 3; r++) {
    // This checks wrong cells!
}

// โœ“ CORRECT - Multiply by 3 to get starting position
int boxRow = (row / 3) * 3;
int boxCol = (col / 3) * 3;
for (int r = boxRow; r < boxRow + 3; r++) {
    for (int c = boxCol; c < boxCol + 3; c++) {
        // Now checking correct 3ร—3 box
    }
}

Mistake 3: Modifying board in isValid

// โŒ WRONG - Validation should not modify board!
private boolean isValid(char[][] board, int row, int col, char digit) {
    board[row][col] = digit;  // Modifying!
    // Check...
    board[row][col] = '.';
    return valid;
}

// โœ“ CORRECT - Only check, don't modify
private boolean isValid(char[][] board, int row, int col, char digit) {
    // Check row, col, box
    // Don't modify board!
    return valid;
}

Mistake 4: Not returning true when solved

// โŒ WRONG - Keeps searching even after solution found!
if (solve(board)) {
    // Continue to next iteration!
}

// โœ“ CORRECT - Return immediately when solved
if (solve(board)) {
    return true;  // Solved! Stop searching!
}

Mistake 5: Checking board[row][col] in validation

// โŒ WRONG - Checks cell being filled!
private boolean isValid(char[][] board, int row, int col, char digit) {
    for (int c = 0; c < 9; c++) {
        if (board[row][c] == digit) {  // Checks (row, col) too!
            return false;
        }
    }
}

// โœ“ CORRECT - Skip the cell being filled
private boolean isValid(char[][] board, int row, int col, char digit) {
    for (int c = 0; c < 9; c++) {
        if (c != col && board[row][c] == digit) {  // Skip (row, col)
            return false;
        }
    }
}
// OR: Check before placing (like in our main solution)


๐ŸŽฏ Pattern Recognition

Problem Type: Constraint Satisfaction
Core Pattern: Backtracking with Validation

When to Apply:
โœ“ Must satisfy multiple constraints
โœ“ Need to fill cells/slots with values
โœ“ Constraints are interdependent
โœ“ Guaranteed unique solution

Recognition Keywords:
- "solve a puzzle"
- "satisfy rules/constraints"
- "valid placement"
- "fill the grid"

Similar Problems:
- N-Queens (LC 51) - Place queens without conflicts
- Valid Sudoku (LC 36) - Just validate, don't solve
- Sudoku Solver variants - Different grid sizes

Key Components:
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Backtracking: Try values, undo if fail    โ”‚
โ”‚ Validation: Check row, col, box           โ”‚
โ”‚ Base case: No empty cells โ†’ solved!       โ”‚
โ”‚ Try all: Loop through 1-9                 โ”‚
โ”‚ Prune: Skip invalid early                 โ”‚
โ”‚ Time: O(9^m), Space: O(m) (m=empty cells) โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐Ÿง  Interview Strategy

Step 1: "This is backtracking with constraint checking"
Step 2: "Find empty cell, try 1-9, validate each"
Step 3: "If valid, place and recurse. If stuck, backtrack"

Key Points to Mention:
- Three constraints: row, column, 3ร—3 box
- Try each digit 1-9 for empty cell
- Validate before placing
- Backtrack if path fails
- Modify board in-place

Walk Through:
"For this board:

 Find first empty at (0,2)
 Try 1: Check row 0, col 2, box 0 โ†’ Valid? Try it
        Recurse to next empty...
        If later fails โ†’ Come back, remove 1
 Try 2: Check constraints โ†’ Valid? Try it
        Recurse...

 Continue until board complete or backtrack when stuck"

Validation Explanation:
"For placing digit at (row, col):

 ROW: Check if digit in board[row][0..8]
 COL: Check if digit in board[0..8][col]
 BOX: Calculate box start: (row/3)*3, (col/3)*3
      Check 3ร—3 region from box start

 If all three pass โ†’ Valid!"

Complexity:
"Time: O(9^m) where m = empty cells
      Each cell: try 9 digits
      m cells: 9^m possibilities
      But pruning makes it much faster!

 Space: O(m) recursion depth
        Each level: one empty cell
        Depth = number of empty cells"

Optimizations (if asked):
"1. Precompute empty cells list
 2. Try digits with fewest conflicts first
 3. Use bitsets for faster validation
 But basic backtracking is sufficient!"

๐Ÿ“ Quick Revision Notes

๐ŸŽฏ Core Concept:

Sudoku Solver: Use backtracking to fill empty cells. For each empty cell, try digits 1-9. For each digit, validate (check row, col, 3ร—3 box). If valid, place digit and recurse. If recursion fails, backtrack (remove digit, try next). Continue until board complete. Box calculation: (row/3)*3, (col/3)*3.

โšก Quick Implementation:

public class Solution {
  public void solveSudoku(char[][] a) {
    backtracking(a);
  }

  private boolean backtracking(char[][] a) {
    // step 1: start looping through each cell looking for empty cell.
    for (int i = 0; i < a.length; i++) {
      for (int j = 0; j < a.length; j++) {
        // step 2: empty cell found
        if (a[i][j] == '.') {
          // step 3: try each digit for that empty cell if it fits
          for (char k = '1'; k <= '9'; k++) {
            // step 4: can we place 'c' at (i, j)?
            if (isValid(a, i, j, k)) {
              // step 5: if we can place 'c' at (i, j), update the character
              // in the board and solve for remaining empty cells
              a[i][j] = k;

              // step 6: solve for remaining.
              // if solved for remaining, return true from here only
              // and no need to try anything else.
              if (backtracking(a)) {
                return true;
              }

              // step 7: if above try failed, backtracking with new digit
              a[i][j] = '.';
            }
          }

          // step 8: you tried all digits and nothing worked for this cell
          return false;
        }
      }
    }

    // step 9: there are no more empty cells.
    // Sudoku is successfully solved, so returns true
    return true;
  }

  private boolean isValid(char[][] a, int row, int col, char ch) {
    // step 10: check all chars in 'row'
    for (int c = 0; c < a[0].length; c++) {
      if (a[row][c] == ch) {
        return false;
      }
    }

    // step 11: check all chars in 'col'
    for (int r = 0; r < a.length; r++) {
      if (a[r][col] == ch) {
        return false;
      }
    }

    // step 12: check all chars in the 'box'
    int boxRow = (row / 3) * 3;
    int boxCol = (col / 3) * 3;

    for (int r = boxRow; r < boxRow + 3; r++) {
      for (int c = boxCol; c < boxCol + 3; c++) {
        if (a[r][c] == ch) {
          return false;
        }
      }
    }

    return true;
  }

  public static void main(String[] args) {
    Solution s = new Solution();

    char[][] 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' }
    };

    s.solveSudoku(board);

    for (int i = 0; i < board.length; i++) {
      for (int j = 0; j < board[0].length; j++) {
        System.out.print(board[i][j] + " ");
      }
      System.out.println();
    }

  }
}

๐Ÿ”‘ Key Insights:

  • Pattern: Constraint Satisfaction with Backtracking
  • 3 Constraints: Row, Column, 3ร—3 Box (all must be checked!)
  • Try 1-9: For each empty cell
  • Validate First: Before placing digit
  • Backtrack: MUST remove digit if path fails
  • Box Calculation: (row/3)*3 and (col/3)*3 for start
  • Time: O(9^m) where m = empty cells, Space: O(m) โœ“

๐ŸŽช Memory Aid:

"Find empty, try 1-9, check row-col-box, backtrack if stuck!"
"Box start: (row/3)3, (col/3)3!" โœจ

โš ๏ธ Critical Points:

Box Calculation - THE INTUITIVE EXPLANATION:

Goal: Given cell (row, col), find top-left corner of its 3ร—3 box

Think in terms of GROUPS:
  Rows divided into 3 groups:
    Group 0: rows 0,1,2 (starts at row 0)
    Group 1: rows 3,4,5 (starts at row 3)
    Group 2: rows 6,7,8 (starts at row 6)

  Cols divided into 3 groups:
    Group 0: cols 0,1,2 (starts at col 0)
    Group 1: cols 3,4,5 (starts at col 3)
    Group 2: cols 6,7,8 (starts at col 6)

Formula: boxRow = (row / 3) * 3

Step-by-step for cell (4, 5):

  ROW:
    row / 3 = 4 / 3 = 1        โ† Which group? Group 1
    1 * 3 = 3                  โ† Group 1 starts at row 3
    boxRow = 3 โœ“

  COL:
    col / 3 = 5 / 3 = 1        โ† Which group? Group 1
    1 * 3 = 3                  โ† Group 1 starts at col 3
    boxCol = 3 โœ“

  Box starts at (3, 3) โœ“

Visual for (4, 5):
     0  1  2 | 3  4  5 | 6  7  8
  3  .  .  . |โฌ†๏ธ .  . | .  .  .  โ† boxRow = 3
  4  .  .  . | .  X  . | .  .  .  โ† row=4, col=5
  5  .  .  . | .  .  . | .  .  .
              โฌ†๏ธ
           boxCol = 3

The pattern:
  Division by 3 โ†’ Which group (0, 1, or 2)?
  Multiply by 3 โ†’ Where does that group start (0, 3, or 6)?

All possible box starts: (0,0), (0,3), (0,6), 
                         (3,0), (3,3), (3,6),
                         (6,0), (6,3), (6,6)
Always multiples of 3!

Alternative formula (same result):
  boxRow = row - (row % 3)
  "Round down to nearest multiple of 3"

Backtracking (MUST DO!):
  board[row][col] = digit;
  if (solve(board)) return true;
  board[row][col] = '.';  โ† CRITICAL!

  Without this:
    Digit stays even when path fails! โœ—

Return Values:
  - return true: Board solved OR path succeeds
  - return false: No valid digit for this cell
  - No empty cell found: Board complete โ†’ true

๐Ÿงช Edge Cases

Case 1: Almost solved (1 cell empty)

Only one cell needs filling
Quick solution

Case 2: Many empty cells

Harder, more backtracking needed
Still solvable with backtracking

Case 3: Requires deep backtracking

Early choices lead to dead ends
Must backtrack many levels
Algorithm handles it correctly

All handled by backtracking! โœ“


๐ŸŽ“ Complexity Analysis

Time Complexity: O(9^m)

Where m = number of empty cells

Why?
  Each empty cell: try up to 9 digits
  m cells: 9 ร— 9 ร— 9 ร— ... (m times) = 9^m

  Worst case: m = 81 (all empty)
    9^81 = huge number!

  But pruning (validation) eliminates most paths early!
  Actual runtime much better than worst case.

Example:
  m = 50 empty cells
  Worst case: 9^50 = 5 ร— 10^47
  With pruning: ~10^6 - 10^9 operations (practical!)

Space Complexity: O(m)

Recursion stack depth:
  Maximum depth = m (number of empty cells)

  Each recursive call: O(1) space
  Total: O(m)

Board modification: In-place (O(1))

Total: O(m) auxiliary space

Same Core Pattern: - N-Queens (LC 51) - Backtracking with constraints - Valid Sudoku (LC 36) - Just validation (no solving) - Sudoku Solver variants - Different grid sizes

Similar Backtracking: - Word Search (LC 79) - Path finding on grid - Combination Sum (LC 39) - Try values with constraints - Permutations (LC 46) - Generate all arrangements


Happy practicing! ๐ŸŽฏ

Note: This is the classic constraint satisfaction problem! Master this and you understand: (1) backtracking with multiple constraints, (2) in-place modification and restoration, (3) pruning invalid paths early, (4) box/grid indexing. Very impressive problem for FAANG interviews - shows deep understanding of backtracking! The key trick is the box calculation: (row/3)*3 and (col/3)*3! ๐Ÿ’ชโœจ