Tutorials Logic, IN +91 8092939553 info@tutorialslogic.com
FAQs Support
Navigation
Home About Us Contact Us Blogs FAQs
Tutorials
All Tutorials
Services
Academic Projects Resume Writing Interview Questions Website Development
Compiler Tutorials

Backtracking

What is Backtracking?

Backtracking is a systematic method for solving constraint satisfaction problems. It builds a solution incrementally and abandons (backtracks) a partial solution as soon as it determines that it cannot lead to a valid complete solution.

Think of it as a depth-first search through a decision tree, with pruning to cut off branches that can't lead to a solution.

  • Choose — make a choice (place a queen, assign a color)
  • Explore — recursively explore with that choice
  • Unchoose — if the choice leads to failure, undo it and try the next option

N-Queens Problem

Place N queens on an N×N chessboard so that no two queens attack each other (no two queens share the same row, column, or diagonal).

N-Queens Problem
public class NQueens {

    static int n;
    static int[] board;  // board[row] = column of queen in that row
    static int solutions = 0;

    static boolean isSafe(int row, int col) {
        for (int r = 0; r < row; r++) {
            if (board[r] == col) return false;  // same column
            if (Math.abs(board[r] - col) == Math.abs(r - row)) return false;  // diagonal
        }
        return true;
    }

    static void solve(int row) {
        if (row == n) {
            solutions++;
            printBoard();
            return;
        }
        for (int col = 0; col < n; col++) {
            if (isSafe(row, col)) {
                board[row] = col;    // CHOOSE: place queen
                solve(row + 1);      // EXPLORE
                board[row] = -1;     // UNCHOOSE: remove queen (backtrack)
            }
        }
    }

    static void printBoard() {
        System.out.println("Solution " + solutions + ":");
        for (int r = 0; r < n; r++) {
            for (int c = 0; c < n; c++) {
                System.out.print(board[r] == c ? "Q " : ". ");
            }
            System.out.println();
        }
        System.out.println();
    }

    public static void main(String[] args) {
        n = 4;
        board = new int[n];
        java.util.Arrays.fill(board, -1);
        solve(0);
        System.out.println("Total solutions for " + n + "-Queens: " + solutions);
        // 4-Queens has 2 solutions
    }
}
Subset Sum Problem
import java.util.ArrayList;
import java.util.List;

public class SubsetSum {

    // Find all subsets that sum to target
    static void findSubsets(int[] arr, int target, int idx,
                            int currentSum, List<Integer> current) {
        if (currentSum == target) {
            System.out.println("Found: " + current);
            return;
        }
        if (idx == arr.length || currentSum > target) return;  // prune

        // CHOOSE: include arr[idx]
        current.add(arr[idx]);
        findSubsets(arr, target, idx + 1, currentSum + arr[idx], current);

        // UNCHOOSE: exclude arr[idx] (backtrack)
        current.remove(current.size() - 1);
        findSubsets(arr, target, idx + 1, currentSum, current);
    }

    public static void main(String[] args) {
        int[] arr = {3, 1, 4, 2, 2};
        int target = 6;
        System.out.println("Subsets summing to " + target + ":");
        findSubsets(arr, target, 0, 0, new ArrayList<>());
        // Found: [3, 1, 2]
        // Found: [3, 1, 2]
        // Found: [4, 2]
        // Found: [4, 2]
        // Found: [2, 2, 2] — if arr had three 2s
    }
}

Rat in a Maze

Find all paths from the top-left to the bottom-right of a grid, where 1 = open cell and 0 = blocked. The rat can move right or down.

Rat in a Maze — Backtracking
public class RatInMaze {

    static int N;
    static int[][] maze;
    static int[][] solution;
    static int paths = 0;

    // 4 directions: right, down, left, up
    static int[] dr = {0, 1, 0, -1};
    static int[] dc = {1, 0, -1, 0};
    static String[] dir = {"R", "D", "L", "U"};

    static boolean isSafe(int r, int c) {
        return r >= 0 && r < N && c >= 0 && c < N
            && maze[r][c] == 1 && solution[r][c] == 0;
    }

    static void solve(int r, int c, String path) {
        if (r == N - 1 && c == N - 1) {
            paths++;
            System.out.println("Path " + paths + ": " + path);
            return;
        }

        solution[r][c] = 1;  // CHOOSE: mark as visited

        for (int d = 0; d < 4; d++) {
            int nr = r + dr[d];
            int nc = c + dc[d];
            if (isSafe(nr, nc)) {
                solve(nr, nc, path + dir[d]);  // EXPLORE
            }
        }

        solution[r][c] = 0;  // UNCHOOSE: unmark (backtrack)
    }

    public static void main(String[] args) {
        N = 4;
        maze = new int[][]{
            {1, 0, 0, 0},
            {1, 1, 0, 1},
            {0, 1, 0, 0},
            {0, 1, 1, 1}
        };
        solution = new int[N][N];

        System.out.println("All paths from (0,0) to (" + (N-1) + "," + (N-1) + "):");
        solve(0, 0, "");
        System.out.println("Total paths: " + paths);
    }
}

/*
 * Maze:
 * 1 0 0 0
 * 1 1 0 1
 * 0 1 0 0
 * 0 1 1 1
 *
 * Path 1: DDRDRR  (Down, Down, Right, Down, Right, Right)
 */

Backtracking Complexity

Backtracking is generally exponential in the worst case, but pruning can dramatically reduce the actual search space:

ProblemWorst CaseWith Pruning
N-QueensO(N!)Much less in practice
Subset SumO(2⊃n)O(2⊃n) worst, better with pruning
PermutationsO(n!)O(n!) — must generate all
SudokuO(9&sup8;¹)Milliseconds with constraint propagation
Graph ColoringO(k⊃n)Better with forward checking

Ready to Level Up Your Skills?

Explore 500+ free tutorials across 20+ languages and frameworks.