Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 44

Backtracking: Depth-First Search in State-Space Trees

Recommended resources

Hello! Welcome to the first lesson of our module on backtracking.

In our previous module, we focused on algorithmic paradigms like Dynamic Programming and Greedy strategies, which are primarily used to solve optimization problems (e.g., finding the shortest path or the maximum value). Now, we are shifting gears to a different class of problems: constraint satisfaction problems. These are problems where we need to find a solution—any solution, or perhaps all possible solutions—that adheres to a specific set of rules.

Today's lesson introduces the fundamental concepts of backtracking. Our goal is to describe the backtracking paradigm as a form of depth-first search on a state-space tree. We'll break down what this means, moving from the high-level idea of an exhaustive search to the more refined and efficient process that backtracking represents.

1. The Core Idea: Searching for Solutions

At its heart, backtracking is a systematic way of trying out all possible sequences of decisions to find a solution. Unlike a greedy algorithm that commits to a choice, backtracking is prepared to undo a choice and try another if the current path isn't leading to a valid solution.

This approach is particularly useful for problems like solving Sudoku, navigating a maze, or finding all permutations of a set of items. The key is that we build a solution step-by-step, and at each step, we check if we've violated any of the problem's constraints.

Let's begin with a video that introduces this general method.

6 Introduction to Backtracking - Brute Force Approach

This video from Abdul Bari provides an excellent introduction to backtracking. It contrasts it with dynamic programming and introduces the core idea of using a brute-force approach to find all possible solutions.

Please watch the first 47 seconds of the video (00:00 - 00:47). Focus on how backtracking is framed as a strategy to find all solutions to a problem, rather than a single optimal one.

This idea of exploring "all possible solutions" can be visualized as a tree structure, which is central to understanding how backtracking works.


2. The State-Space Tree

The set of all possible paths or decision sequences in a backtracking problem can be organized into a state-space tree.

  • The root of the tree represents the initial state, before any decisions have been made.
  • Each node in the tree represents a partial solution or a specific state reached after a sequence of choices.
  • Each branch represents a choice that moves us from one state to another.
  • The leaves of the tree represent either complete, valid solutions or dead ends.

Imagine you're solving a maze. The root is the entrance. Each time you reach an intersection, you create branches in the tree for each possible turn (left, right, straight). A path from the root to a leaf represents a complete journey through the maze.

State-Space Tree in Backtracking Algorithm
This image provides a simple visual of a state-space tree. The algorithm starts at the root, explores a path (green circles), and if it hits a dead end ('Not a solution'), it 'backtracks' to a previous decision point to explore another branch.

To formalize this, let's look at how the problem's solution space is modeled as this tree.

[PDF] Module 5: Backtracking

This document provides a formal definition of the state-space tree and introduces the concepts of 'promising' and 'non-promising' nodes, which are key to the efficiency of backtracking.

Please read the sections titled 'Backtracking' and the paragraph that follows describing the state-space tree. You can find this on page 5.2. Focus on the definitions of the root, nodes, promising nodes, and non-promising nodes.

A node is promising if the partial solution it represents can still lead to a valid complete solution. It's non-promising if we can determine that no matter what further choices we make from this point, we can never reach a valid solution. This is where the "intelligence" of backtracking comes in—we stop exploring as soon as a node becomes non-promising.


3. Traversing the Tree: A Depth-First Approach

Now for the central part of our learning outcome: how does backtracking actually explore this state-space tree? It does so using a Depth-First Search (DFS).

Recall from our graph traversal module that DFS explores as far as possible along each branch before backtracking. This is exactly what a backtracking algorithm does:

  1. Start at the root.
  2. Choose one branch and go down one level.
  3. Repeat this process, going deeper and deeper into the tree.
  4. If you reach a valid solution, record it.
  5. If you reach a non-promising node (a dead end) or a leaf that isn't a solution, you backtrack: you go back up to the parent node and try the next unexplored branch.

This video makes the connection between backtracking and DFS explicit.

6 Introduction to Backtracking - Brute Force Approach

In this segment, Abdul Bari clearly explains that the exploration strategy used in backtracking is DFS. He also contrasts it with Breadth-First Search (BFS), which is used in a different paradigm called Branch and Bound.

Please watch the segment from 06:19 to 08:12. The key takeaway is the direct statement that backtracking follows a Depth-First Search pattern.

With your software engineering background, you'll appreciate a more formal definition. The following resource presents backtracking search as a recursive algorithm and analyzes its complexity, which aligns with the DFS traversal pattern.

[PDF] Lecture 5: Search I

This excerpt from a Stanford lecture on search algorithms formally defines backtracking search, provides pseudocode, and discusses its time and memory complexity. This provides the rigorous underpinning for the concepts we've discussed.

Read the sections 'Backtracking search' and the pseudocode provided on pages 27-29. Note the recursive structure, which naturally implements a DFS traversal. Also, pay attention to the complexity analysis: O(D) for memory and O(b^D) for time, where D is the depth and b is the branching factor.

The memory complexity of is a direct result of the DFS approach. Since we only need to store the current path from the root to the node we are visiting, the memory usage is proportional to the depth of the tree, not its total number of nodes. This makes backtracking feasible for very large search spaces where a BFS approach (which would require storing all nodes at a given level) would run out of memory.


4. The Power of Pruning

If backtracking just explored every single node in the state-space tree, it would be a simple brute-force search. Its true power lies in pruning: the ability to discard large portions of the state-space tree.

As soon as we determine a node is "non-promising" because it violates a problem constraint, we don't just stop at that node—we refuse to generate any of its descendants. This is the "backtracking" step in action. By cutting off entire subtrees, we can achieve massive performance gains over a naive exhaustive search.

This concept is also known as applying a bounding function.

6 Introduction to Backtracking - Brute Force Approach

Let's return to the Abdul Bari video to see a concrete example of pruning. He introduces a constraint to a simple permutation problem and shows how it allows us to 'kill' nodes and avoid exploring fruitless paths.

Watch the segment from 03:48 to 06:05. Observe how imposing a simple rule ('girls should not sit in the middle') prunes the state-space tree.

Backtracking State-Space Tree for Permutations
This image shows a state-space tree for generating permutations. The red crosses indicate where the algorithm has pruned the search. By identifying that a partial solution (e.g., `{1, 1, ...}`) violates the constraint of using unique numbers, the algorithm backtracks immediately without exploring any further down that path.

Conclusion

In this lesson, we have laid the conceptual foundation for the backtracking paradigm. It's a powerful technique for solving problems that can be modeled as a search for a valid configuration among many possibilities.

Key Takeaways:

  • Backtracking is an algorithmic paradigm for solving constraint satisfaction problems by systematically exploring all possible candidates.
  • The search space is conceptualized as a state-space tree, where paths from the root represent partial solutions.
  • Backtracking explores this tree using a Depth-First Search (DFS) traversal, which makes it very memory-efficient ( space).
  • Its efficiency comes from pruning: it abandons a path as soon as it determines the path cannot lead to a valid solution (i.e., the node becomes "non-promising").

Preview of the Next Lesson:

Now that we understand the theory, it's time to put it into practice. In the next lesson, we will apply backtracking to solve the classic N-Queens problem. We'll define the state, identify the constraints that allow for pruning, and walk through the construction of a recursive solution.