Bird
Raised Fist0
Interview PrepbacktrackinghardAmazonFacebookGoogleSnap

Sudoku Solver

Choose your preparation mode4 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
📋
Problem

Imagine you have a partially completed Sudoku puzzle and want a program to fill in the missing numbers correctly, respecting all Sudoku rules.

Given a 9x9 Sudoku board partially filled with digits 1-9 and empty cells represented by '.', fill the board so that every row, every column, and every 3x3 sub-box contains the digits 1 through 9 exactly once. Modify the board in-place.

board is a 9x9 gridEach cell contains a digit '1'-'9' or '.' for emptyThe input board is guaranteed to have a valid solution
Edge cases: Board with only one empty cell → should fill that cell correctlyBoard with multiple empty cells in the same row/column/box → must respect all constraintsBoard with minimal clues (17 clues) → still solvable by backtracking
</>
IDE
def solveSudoku(board: list[list[str]]) -> None:public void solveSudoku(char[][] board)void solveSudoku(vector<vector<char>>& board)function solveSudoku(board)
def solveSudoku(board):
    # Write your solution here
    pass
class Solution {
    public void solveSudoku(char[][] board) {
        // Write your solution here
    }
}
#include <vector>
using namespace std;

void solveSudoku(vector<vector<char>>& board) {
    // Write your solution here
}
function solveSudoku(board) {
    // Write your solution here
}
0/9
Common Bugs to Avoid
Wrong: Board with repeated digits in a row or columnMissing or incorrect checks for row or column constraints before placing a digit.Implement is_valid function to check that digit does not appear in the same row or column before placement.
Wrong: Board with repeated digits in a 3x3 boxBox constraint not checked or off-by-one error in box indexing.Check all cells in the 3x3 box using correct box start indices: rowStart=3*(r//3), colStart=3*(c//3).
Wrong: Incomplete board or no solution foundBacktracking does not revert changes or stops prematurely.Ensure backtracking resets cell to '.' when no digit fits and continues searching other digits.
Wrong: Solver times out on empty or large boardsBrute force backtracking without pruning or heuristics.Implement constraint propagation and choose the most constrained empty cell first to reduce branching.
Test Cases
t1_01basic
Input[[["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"]]]
Expected[[["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"]]]

The solver fills each empty cell by trying digits 1-9 and backtracking when constraints are violated, eventually completing the board correctly.

t1_02basic
Input[[["8",".",".",".",".",".",".",".","."],[".",".","3","6",".",".",".",".","."],[".","7",".",".","9",".","2",".","."],[".","5",".",".",".","7",".",".","."],[".",".",".",".","4","5","7",".","."],[".",".",".","1",".",".",".","3","."],[".",".","1",".",".",".",".","6","8"],[".",".","8","5",".",".",".","1","."],[".","9",".",".",".",".","4",".","."]]]
Expected[[["8","1","2","7","5","3","6","4","9"],["9","4","3","6","8","2","1","7","5"],["6","7","5","4","9","1","2","8","3"],["1","5","4","2","3","7","8","9","6"],["3","6","9","8","4","5","7","2","1"],["2","8","7","1","6","9","5","3","4"],["5","2","1","9","7","4","3","6","8"],["4","3","8","5","2","6","9","1","7"],["7","9","6","3","1","8","4","5","2"]]]

Another standard Sudoku puzzle solved by backtracking with constraint checks, filling all empty cells correctly.

t2_01edge
Input[[["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","."]]]
Expected[[["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"]]]

Board with only one empty cell; solver must fill that cell correctly without unnecessary backtracking.

t2_02edge
Input[[["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"]]]
Expected[[["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"]]]

Board with multiple empty cells in the same row, column, and box; solver must respect all constraints simultaneously.

t2_03edge
Input[[[".",".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".",".","."]]]
Expectednull

Empty board (all cells empty) is a boundary case; solver must handle but will be very slow for brute force.

t3_01corner
Input[[["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"]]]
Expected[[["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"]]]

Test to catch greedy approach that fills cells without backtracking, leading to invalid final board.

t3_02corner
Input[[["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"]]]
Expected[[["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"]]]

Test to catch confusion between 0/1 constraints and unbounded filling (not applicable here but to ensure no repeated digits).

t3_03corner
Input[[["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"]]]
Expected[[["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"]]]

Test to catch off-by-one errors in indexing 3x3 boxes or rows/columns.

t4_01performance
Input[[[".",".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".",".","."]]]
⏱ Performance - must finish in 2000ms

Empty board with all cells empty (81 empty cells) tests solver performance; brute force backtracking is O(9^81) and will time out.

Practice

(1/5)
1. Given the following code for next permutation, what is the content of the array nums after calling next_permutation([1, 3, 2])?
easy
A. [1, 2, 3]
B. [2, 3, 1]
C. [2, 1, 3]
D. [1, 3, 2]

Solution

  1. Step 1: Trace the pivot search

    Start with i = 1 (index of 3). Since nums[1]=3 >= nums[2]=2, decrement i to 0. nums[0]=1 < nums[1]=3, so pivot i=0.
  2. Step 2: Find j to swap with pivot

    Start j=2 (value 2). nums[2]=2 > nums[0]=1, so j=2. Swap nums[0] and nums[2]: array becomes [2,3,1]. Then reverse suffix from i+1=1 to end: reverse [3,1] -> [1,3]. Final array: [2,1,3].
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Array changes from [1,3,2] to [2,1,3] after next permutation [OK]
Hint: Pivot found at first decreasing from right, swap and reverse suffix [OK]
Common Mistakes:
  • Swapping with wrong element
  • Not reversing suffix after swap
2. What is the time complexity of the optimal iterative approach using a queue to generate all letter combinations for a digit string of length n, assuming each digit maps to at most 4 letters?
medium
A. O(n * 4^n) because we process each digit and expand combinations exponentially
B. O(2^n) because each digit doubles the number of combinations
C. O(4^n * n) because there are up to 4^n combinations and each combination is built with n concatenations
D. O(n^2) because we process n digits and each combination takes n steps

Solution

  1. Step 1: Identify number of combinations

    Each digit maps to up to 4 letters, so total combinations are up to 4^n.
  2. Step 2: Analyze work per combination

    Each combination is built by concatenating letters for n digits, so each combination requires O(n) time to build.
  3. Step 3: Simplify complexity expression

    O(4^n * n) and O(n * 4^n) are equivalent; however, O(n * 4^n) because we process each digit and expand combinations exponentially is the standard notation emphasizing processing each digit and expanding combinations exponentially.
  4. Final Answer:

    Option A -> Option A
  5. Quick Check:

    Time is exponential in n with linear cost per combination [OK]
Hint: Exponential combinations times linear build cost [OK]
Common Mistakes:
  • Confusing exponential base (2 vs 4)
  • Ignoring concatenation cost per combination
3. Consider the following code snippet for palindrome partitioning. Which line contains a subtle bug that causes incorrect or duplicate partitions?
def partition(s):
    def is_palindrome(left, right):
        while left < right:
            if s[left] != s[right]:
                return False
            left += 1
            right -= 1
        return True

    def backtrack(start, path):
        if start == len(s):
            result.append(path)  # Line X
            return
        for end in range(start, len(s)):
            if is_palindrome(start, end):
                path.append(s[start:end+1])
                backtrack(end+1, path)
                path.pop()

    result = []
    backtrack(0, [])
    return result
medium
A. Line 6: palindrome check misses single character substrings
B. Line X: appending path without copying causes shared references
C. Line 12: for loop range should be from start+1 to len(s)+1
D. Line 15: missing path.pop() after backtrack call

Solution

  1. Step 1: Identify how results are stored

    Appending path directly stores a reference, so later modifications affect all stored results.
  2. Step 2: Correct approach

    Use result.append(path[:]) to append a copy, preserving each partition snapshot.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Shared references cause incorrect final partitions [OK]
Hint: Always append a copy of path to results [OK]
Common Mistakes:
  • Forgetting to copy path before appending
  • Incorrect palindrome check boundaries
  • Forgetting to pop after recursion
4. What is the time complexity of generating all permutations of an array of length n using Heap's algorithm, and why might a common misconception about this complexity be incorrect?
medium
A. O(n! * n^2) because each permutation requires n swaps and there are n! permutations
B. O(n! * log n) because Heap's algorithm uses a heap data structure internally
C. O(n! * n) because each of the n! permutations requires copying the array of length n
D. O(n! + n) because generating permutations is factorial plus linear overhead

Solution

  1. Step 1: Identify number of permutations

    There are n! permutations for an array of length n.
  2. Step 2: Analyze cost per permutation

    Heap's algorithm generates each permutation with O(1) swaps, but copying the current permutation to the result list takes O(n) time.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Time complexity is O(n! * n) due to copying each permutation [OK]
Hint: Copying each permutation costs O(n), not the swaps themselves [OK]
Common Mistakes:
  • Assuming swaps cost O(n) each or confusing heap data structure usage
5. Suppose the N-Queens problem is modified so that queens can be placed multiple times in the same column (i.e., column constraint is relaxed), but diagonal attacks still apply. Which modification to the bitmask backtracking algorithm correctly adapts to this variant?
hard
A. Remove the column bitmask tracking and only track diagonal attacks in recursion
B. Keep column bitmask but allow multiple queens by resetting it each row
C. Use a greedy approach placing queens in any column without pruning
D. Track columns as before but ignore diagonal bitmasks

Solution

  1. Step 1: Understand relaxed constraints

    Since columns can have multiple queens, column bitmask is no longer needed to prune placements.
  2. Step 2: Adapt pruning to only diagonal attacks

    Keep diag1 and diag2 bitmasks to prune diagonal conflicts, but remove column mask from available_positions calculation.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Removing column mask allows multiple queens per column while still pruning diagonals [OK]
Hint: Relaxed constraints remove column pruning, keep diagonal pruning [OK]
Common Mistakes:
  • Resetting column mask each row incorrectly
  • Ignoring diagonal pruning
  • Using greedy without pruning