← System Design Simulator

Sudoku Solver Visualization for Coding Interviews

By Rahul Kumar · Senior Software Engineer · Updated · Category: Greedy & Backtracking

Backtracking with constraint propagation — watch it backtrack.

Concept

A Sudoku solver is the friendly face of constraint satisfaction: fill a 9x9 grid with digits 1-9 such that every row, column, and 3x3 box contains all nine digits without repetition. The elegance of backtracking makes it approachable, while the performance differences between a naive approach and a constraint-propagation solver can be several orders of magnitude. Real-world solvers combine DFS backtracking with heuristics like MRV (minimum remaining values — pick the empty cell with the fewest candidates first) and AC-3 style constraint propagation. For interviews and puzzle apps the straightforward 'try each digit 1-9 and recurse' solver using bitmask-based conflict tracking is fast enough — most newspaper Sudokus solve in well under a millisecond. The same ideas generalize to Kakuro, Killer Sudoku, and scheduling with unary domain constraints.

Sudoku Solver — Interactive Simulator

Runs fully client-side in your browser; no sign-up. Or open full screen →

Launch the interactive Sudoku Solver visualization — animated algorithm, step-through, and live data-structure updates.

How it works

Backtracking fills empty cells one at a time. Find the next empty cell (convention: scan row-major). For each candidate digit 1-9, check that it does not appear in the same row, column, or 3x3 box. If valid, place it and recurse; if the recursive call succeeds (found a complete solution), propagate success. If it fails, unplace the digit and try the next one. If no digit works, return failure and let the caller backtrack. Naively checking conflicts scans 27 cells per placement (O(n) per cell, 81 cells, lots of redundant work). A much faster version maintains three bitmasks per row, column, and box — each a 9-bit integer where bit d is set if digit d+1 is already used. Placement becomes an O(1) update: check (rowMask[r] | colMask[c] | boxMask[b]) has bit d unset, then set the bit; backtracking clears the bit. With this structure plus MRV cell ordering, even the notorious 'hardest Sudoku' from Arto Inkala solves in milliseconds. The algorithm is complete — if a solution exists it will be found, and if the puzzle is unsolvable it will report failure after exhausting the tree.

Implementation

SudokuSolver.java — in-place backtracking
public final class SudokuSolver {
    private SudokuSolver() {}

    public static boolean solveSudoku(char[][] board) {
        int[] rows = new int[9];
        int[] cols = new int[9];
        int[] boxes = new int[9];
        for (int r = 0; r < 9; r++) {
            for (int c = 0; c < 9; c++) {
                if (board[r][c] != '.') {
                    int d = board[r][c] - '1';
                    int bit = 1 << d;
                    rows[r] |= bit;
                    cols[c] |= bit;
                    boxes[(r / 3) * 3 + c / 3] |= bit;
                }
            }
        }
        return backtrack(board, 0, rows, cols, boxes);
    }

    private static boolean backtrack(char[][] board, int pos, int[] rows, int[] cols, int[] boxes) {
        if (pos == 81) return true;
        int r = pos / 9, c = pos % 9;
        if (board[r][c] != '.') return backtrack(board, pos + 1, rows, cols, boxes);
        int b = (r / 3) * 3 + c / 3;
        int used = rows[r] | cols[c] | boxes[b];
        int available = (~used) & 0x1FF;
        while (available != 0) {
            int bit = available & -available;
            available ^= bit;
            int d = Integer.numberOfTrailingZeros(bit);
            board[r][c] = (char) ('1' + d);
            rows[r] |= bit; cols[c] |= bit; boxes[b] |= bit;
            if (backtrack(board, pos + 1, rows, cols, boxes)) return true;
            rows[r] ^= bit; cols[c] ^= bit; boxes[b] ^= bit;
        }
        board[r][c] = '.';
        return false;
    }

    public static boolean isValid(char[][] board) {
        int[] rows = new int[9], cols = new int[9], boxes = new int[9];
        for (int r = 0; r < 9; r++) {
            for (int c = 0; c < 9; c++) {
                if (board[r][c] == '.') continue;
                int d = board[r][c] - '1';
                if (d < 0 || d >= 9) return false;
                int bit = 1 << d;
                int b = (r / 3) * 3 + c / 3;
                if (((rows[r] | cols[c] | boxes[b]) & bit) != 0) return false;
                rows[r] |= bit; cols[c] |= bit; boxes[b] |= bit;
            }
        }
        return true;
    }
}

Complexity

Common pitfalls

Key design decisions & trade-offs

Practice problems

Interview follow-ups

Why it matters

Sudoku Solver is a core part of the Greedy & Backtracking toolkit. If you are preparing for a technical interview at a top-tier company or teaching a course, a working visualization is the fastest path from "I read about it" to "I understand it".

Related