Sudoku Solver Using Backtracking in DSA Python - Time & Space Complexity
We want to understand how the time needed to solve a Sudoku puzzle changes as the puzzle size or difficulty changes.
Specifically, how does the backtracking method's work grow with the number of empty cells?
Analyze the time complexity of the following Sudoku solver using backtracking.
def solve_sudoku(board):
empty = find_empty_cell(board)
if not empty:
return True
row, col = empty
for num in range(1, 10):
if is_valid(board, row, col, num):
board[row][col] = num
if solve_sudoku(board):
return True
board[row][col] = 0
return False
This code tries numbers 1 to 9 in each empty cell, checking if the number fits, and uses recursion to solve the rest.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Trying numbers 1 to 9 in each empty cell and recursively solving the rest.
- How many times: Up to 9 choices per empty cell, repeated for each empty cell recursively.
Each empty cell can try up to 9 numbers, and for each choice, the solver tries the next empty cell similarly.
| Input Size (empty cells) | Approx. Operations |
|---|---|
| 10 | Up to 9^10 = 3,486,784,401 tries |
| 20 | Up to 9^20 ≈ 1.21e19 tries |
| 30 | Up to 9^30 ≈ 1.21e28 tries |
Pattern observation: The number of operations grows exponentially with the number of empty cells.
Time Complexity: O(9^m) where m is the number of empty cells
This means the time needed can grow very fast as more cells are empty, because each cell tries many possibilities recursively.
[X] Wrong: "The solver always tries exactly 9 options per empty cell, so it's always 9 times the number of empty cells."
[OK] Correct: The solver tries up to 9 options per cell, but it explores many combinations recursively, so the total tries multiply, not just add.
Understanding this exponential growth helps you explain why backtracking can be slow and why pruning or smarter methods matter.
It shows your grasp of recursion and problem-solving limits, which is valuable in interviews.
"What if we added a heuristic to pick the empty cell with the fewest valid options first? How would that affect the time complexity?"
Practice
Solution
Step 1: Understand backtracking role
Backtracking tries numbers in empty cells and removes them if they cause conflicts.Step 2: Compare other options
Other options do not describe backtracking's trial and error approach.Final Answer:
To try possible numbers and undo choices if they lead to conflicts -> Option DQuick Check:
Backtracking = Try and undo choices [OK]
- Thinking backtracking fills randomly without checks
- Confusing backtracking with sorting or counting
- Ignoring the undo step in backtracking
Solution
Step 1: Identify correct function call syntax
Python requires parentheses and a colon after the if condition, so 'if is_safe(board, row, col, num):' is correct.Step 2: Check other options for syntax errors
if isSafe(board, row, col, num); uses semicolon instead of colon; C misses colon; D misses parentheses.Final Answer:
if is_safe(board, row, col, num): -> Option AQuick Check:
Python if syntax = condition + colon [OK]
- Forgetting the colon at the end of if statement
- Missing parentheses around function arguments
- Using semicolon instead of colon
board = [ [5, 3, 0, 0, 7, 0, 0, 0, 0], [6, 0, 0, 1, 9, 5, 0, 0, 0], [0, 9, 8, 0, 0, 0, 0, 6, 0], [8, 0, 0, 0, 6, 0, 0, 0, 3], [4, 0, 0, 8, 0, 3, 0, 0, 1], [7, 0, 0, 0, 2, 0, 0, 0, 6], [0, 6, 0, 0, 0, 0, 2, 8, 0], [0, 0, 0, 4, 1, 9, 0, 0, 5], [0, 0, 0, 0, 8, 0, 0, 7, 9] ] solve_sudoku(board) print(board)
Solution
Step 1: Understand solve_sudoku function effect
The solve_sudoku function fills empty cells (zeros) with correct numbers to complete the Sudoku board.Step 2: Analyze output after solving
After solving, the board will be fully filled with valid numbers, matching [[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]]'s completed grid.Final Answer:
Completed Sudoku board with all zeros replaced by correct numbers -> Option AQuick Check:
Backtracking fills zeros to complete board [OK]
- Expecting the board to remain unchanged after solve
- Confusing syntax or runtime errors with correct output
- Not recognizing that zeros are placeholders for empty cells
def solve(board):
for row in range(9):
for col in range(9):
if board[row][col] == 0:
for num in range(1, 10):
if is_safe(board, row, col, num):
board[row][col] = num
if solve(board):
return True
board[row][col] = 0
return False
return True
# Error: The function is_safe is not defined anywhere.Solution
Step 1: Check for missing functions
The code calls is_safe but does not define it, causing a NameError at runtime.Step 2: Verify other options
Board size 9 is correct for Sudoku; num range 1-9 is correct; solve returns True at end which is correct.Final Answer:
The function is_safe is missing, causing NameError -> Option CQuick Check:
Undefined function causes NameError [OK]
- Assuming board size is 8 instead of 9
- Using wrong range for numbers (should be 1 to 9)
- Forgetting to return True when solved
Solution
Step 1: Understand backtracking optimization
Choosing the empty cell with the fewest valid options reduces branching and speeds solving.Step 2: Evaluate other options
Random filling ignores constraints; trying numbers without checks wastes time; restarting after failure is inefficient.Final Answer:
Always pick the next empty cell with the fewest possible valid numbers -> Option BQuick Check:
Minimum options first = faster backtracking [OK]
- Ignoring constraints when filling cells
- Trying numbers in fixed order without pruning
- Restarting solving unnecessarily wastes time
Ready to prove it?
Pass the test and this pattern moves unknown
