Back to Blog
BacktrackingMedium

Backtracking Algorithms: When and How to Use Them

Deep dive into backtracking algorithms with examples including permutations, combinations, and constraint satisfaction problems.

November 20, 2024
14 min read
BacktrackingRecursionAlgorithms

Backtracking Algorithms: When and How to Use Them


Backtracking is a powerful technique for solving constraint satisfaction problems by exploring all possibilities.


The Backtracking Pattern


  • Make a choice
  • Recursively solve with that choice
  • Undo the choice (backtrack)
  • Try next option

  • Permutations


    Generate all permutations of an array:


    def permute(nums):
        result = []
        
        def backtrack(current):
            if len(current) == len(nums):
                result.append(current[:])
                return
            
            for num in nums:
                if num not in current:
                    current.append(num)
                    backtrack(current)
                    current.pop()  # Backtrack
        
        backtrack([])
        return result

    Combinations


    Generate combinations of k elements:


    def combine(n, k):
        result = []
        
        def backtrack(start, current):
            if len(current) == k:
                result.append(current[:])
                return
            
            for i in range(start, n + 1):
                current.append(i)
                backtrack(i + 1, current)
                current.pop()  # Backtrack
        
        backtrack(1, [])
        return result

    N-Queens Problem


    Place n queens on n×n board without attacking:


    def solve_n_queens(n):
        result = []
        board = [['.'] * n for _ in range(n)]
        
        def is_safe(row, col):
            # Check column
            for i in range(row):
                if board[i][col] == 'Q':
                    return False
            
            # Check diagonals
            for i, j in zip(range(row-1, -1, -1), range(col-1, -1, -1)):
                if board[i][j] == 'Q':
                    return False
            
            for i, j in zip(range(row-1, -1, -1), range(col+1, n)):
                if board[i][j] == 'Q':
                    return False
            
            return True
        
        def backtrack(row):
            if row == n:
                result.append([''.join(row) for row in board])
                return
            
            for col in range(n):
                if is_safe(row, col):
                    board[row][col] = 'Q'
                    backtrack(row + 1)
                    board[row][col] = '.'  # Backtrack
        
        backtrack(0)
        return result

    When to Use Backtracking


  • Constraint satisfaction problems
  • Need to explore all possibilities
  • Problems with "undo" operations
  • Permutations, combinations, subsets

  • Key Tips


  • Pruning: Skip invalid paths early
  • State Management: Track current state
  • Base Case: Define when to stop
  • Cleanup: Always undo changes

  • Backtracking is essential for many interview problems!


    Related Articles

    Binary Search
    A comprehensive guide to binary search algorithms, covering standard search, rotated arrays, and finding boundaries.
    Dynamic Programming
    Understand the fundamentals of dynamic programming with clear examples and when to use memoization vs bottom-up approaches.
    Computer Science
    A beginner-friendly guide to analyzing algorithm efficiency and understanding Big O, Omega, and Theta notation.