Hello! Welcome to the second lesson in our module on backtracking.
In our last session, we dissected the N-Queens problem and saw how the "choose, explore, unchoose" pattern provides a powerful template for solving constraint-satisfaction problems. We defined the core components—choices, constraints, and goals—and explored how pruning the state-space tree is essential for efficiency.
Today, we'll reinforce that understanding by applying the exact same backtracking paradigm to another classic combinatorial search problem: solving a Sudoku puzzle. This will demonstrate the versatility of the backtracking technique and give you more practice in identifying its core components in a new context.
1. Framing Sudoku as a Backtracking Problem
First, let's formally define the problem. A Sudoku puzzle consists of a 9x9 grid, partially filled with numbers. The objective is to fill the empty cells (usually marked with 0) such that every row, every column, and every one of the nine 3x3 subgrids contains the digits 1 through 9 exactly once.
A brute-force approach would involve trying every possible number in every empty cell, leading to an impossibly large search space. Backtracking offers a much more structured and efficient way to navigate this space.
To start, let's watch a video that frames the Sudoku problem using the "choices, constraints, and goal" model we're familiar with.
The Backtracking Blueprint: The Legendary 3 Keys To Backtracking Algorithms
The video "The Backtracking Blueprint" by Back To Back SWE is excellent because it uses Sudoku as its primary example to explain the three fundamental keys of backtracking. This will help us structure our thinking.
Watch the segment from the beginning to 10:38. As you watch, try to map the concepts to what we learned with N-Queens: Choice: What is the fundamental decision being made at each step? Constraints: What rules must each choice obey? Goal: What is the base case that signifies a complete solution? Backtracking: What does it mean to "undo" a choice?
As the video explains, we can define the problem as follows:
- Choice: For a given empty cell, our choice is which number (from 1 to 9) to place in it.
- Constraints: The chosen number must not already exist in the cell's current row, column, or 3x3 subgrid.
- Goal: Our goal is reached when we have successfully filled the entire board, meaning there are no empty cells left.
This process of finding an empty cell, trying a number, checking its validity, and then moving to the next empty cell forms a recursive structure. If we hit a dead end (a cell where no number from 1 to 9 is valid), we must backtrack.
This flowchart provides a high-level overview of the logic we will implement.

2. The Backtracking Algorithm for Sudoku
Now let's translate this conceptual framework into a concrete algorithm. The recursive function will systematically explore the search space.
The core logic, which you'll find is very similar to the N-Queens solver, is as follows:
- Find the next empty cell. We can simply scan the board (e.g., from top-left to bottom-right) to find the first cell that is empty (e.g., contains a
0). - Base Case: If there are no empty cells, we have successfully solved the puzzle. We can return
true. - Recursive Step (Choose, Explore, Unchoose):
- For the found empty cell, iterate through the numbers 1 to 9 (the choices).
- For each number, check if placing it in the current cell is safe (i.e., it doesn't violate Sudoku's rules).
- If it is safe:
- Choose: Place the number in the cell.
- Explore: Make a recursive call to solve the rest of the board from this new state. If this recursive call returns
true, it means a solution was found, so we propagatetrueup the call stack. - Unchoose (Backtrack): If the recursive call returns
false, it means our current choice did not lead to a solution. We must undo the choice by resetting the cell to empty and continue our loop to try the next number.
- If the loop finishes without finding a valid number that leads to a solution, it means this path is a dead end. Return
falseto trigger backtracking in the previous recursive call.
This image helps visualize the crucial backtracking step. When an invalid placement is made, the algorithm reverts the board to a previous state to try a different path.

To see how this logic translates into code, let's examine a well-structured implementation.
The GeeksforGeeks article "Sudoku Solver" provides a clear implementation of the algorithm we've just outlined. Your experience as a software engineer will make the code straightforward to understand.
Read the section titled '[Approach 1] Using Backtracking'. Pay close attention to the Python code. Identify: The main recursive function (solveSudokuRec). The base cases for the recursion. The 'choose, explore, unchoose' pattern within the for loop. The logic of the isSafe function, which enforces the constraints.
The isSafe() function is our pruning mechanism. By checking for conflicts early, we avoid exploring entire subtrees of the search space that are guaranteed to be invalid.
3. Performance and Optimization Strategies
The basic backtracking algorithm will find a solution, but its performance can vary dramatically depending on the puzzle's difficulty. For harder puzzles, the number of recursive calls can explode. This is where more advanced pruning techniques become critical.
Let's watch a short video that empirically demonstrates the performance difference between a pure backtracking solver and one that incorporates logical pruning.
Sudoku solvers: backtracking or logic?
The video "Sudoku solvers: backtracking or logic?" by Games Computers Play compares different solving strategies. We're not focused on the specific Sudoku tricks, but on the performance impact of pruning.
Watch the segments from 02:26-02:56 and 02:56-03:22. Notice the dramatic reduction in time when just one simple pruning strategy ('simple elimination') is added to the pure backtracking solver.
The massive speedup highlights that while backtracking provides the search framework, intelligent pruning is what makes it practical for hard problems. The "simple elimination" mentioned in the video is a form of constraint propagation. Let's give this and other optimization heuristics more formal names.
This paper, 'A Sudoku Solver', discusses several key optimizations for backtracking search that are directly applicable here. It will provide the deeper theoretical insight you appreciate.
Read the sections titled 'Forward Checking', 'Constraint Propagation', and 'Minimum Remaining Values'. Don't worry about the implementation details, but focus on the concepts: Forward Checking: Instead of just checking if a number is valid now, how can we maintain a list of possible valid numbers for all future cells? Constraint Propagation: If a cell ends up with only one possible valid number, we should fill it in immediately. How does this help prune the search tree earlier? Minimum Remaining Values (MRV) Heuristic: Instead of processing cells in a fixed order (e.g., row by row), why is it better to next choose the cell with the fewest possible valid numbers?
These optimizations don't change the fundamental backtracking nature of the algorithm. They are heuristics that guide the search toward more promising branches and help it "fail faster," which is the key to effective pruning. The MRV heuristic, for instance, reduces the branching factor of the state-space tree at its highest levels, leading to exponential gains in performance.
Conclusion
In this lesson, we successfully mapped the backtracking pattern to the Sudoku problem. By framing it in terms of choices, constraints, and a goal, we were able to construct a recursive algorithm that systematically searches for a solution.
Key Takeaways:
- Sudoku is a classic combinatorial search problem that can be elegantly solved with backtracking.
- The "choose, explore, unchoose" pattern is universal: we find an empty cell, try placing a valid number (choose), recursively solve from there (explore), and reset the cell if the path fails (unchoose).
- The
isSafe()function acts as the primary pruning mechanism, preventing the exploration of invalid states. - While basic backtracking works, its performance on harder problems is poor. Advanced pruning heuristics like constraint propagation and the Minimum Remaining Values (MRV) heuristic are crucial for making the solver efficient in practice.
Preview of the Next Lesson:
We've now seen backtracking applied to two distinct problems and have discussed the importance of pruning. In the next lesson, we will focus specifically on implementing pruning strategies. We will take a backtracking problem and see how to augment the basic algorithm with optimizations to significantly reduce the search space and improve its runtime.