← Back to All Patterns

Backtracking Pattern

🔄 Backtracking - Generating Subsets

Current Subset Being Built:

[]

Available Choices:

1
2
3

Step 1: Start with empty set, can add 1, 2, or 3

Subsets Found So Far:

Progress: 1 / 12

Speed:

Key Concept:

Backtracking explores all possibilities by making choices, going deeper, then backtracking (undoing the choice) to try other options.

🎯 Imagine This...

Think of exploring a maze. You try one path, and if it leads to a dead end, you go back (backtrack) and try a different path. You keep trying all possibilities until you find the solution! That's backtracking - try, fail, go back, try again.

Try → Failed? → Go Back → Try Again

When Should You Use This Pattern?

  • Need to find all possible solutions
  • Constraint satisfaction problems
  • Generating combinations or permutations
  • Problems like N-Queens, Sudoku, maze solving

📝 Example 1: Generate All Subsets

Given [1, 2, 3], generate all possible subsets (power set).

Subsets.java
java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import java.util.*;
public class Subsets {
public static List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
backtrack(nums, 0, new ArrayList<>(), result);
return result;
}
private static void backtrack(int[] nums, int start,
List<Integer> current,
List<List<Integer>> result) {
// Add current subset to result
result.add(new ArrayList<>(current));
// Try adding each remaining number
for (int i = start; i < nums.length; i++) {
current.add(nums[i]); // Choose
backtrack(nums, i + 1, current, result); // Explore
current.remove(current.size() - 1); // Backtrack (undo)
}
}
public static void main(String[] args) {
int[] nums = {1, 2, 3};
List<List<Integer>> result = subsets(nums);
System.out.println("All subsets:");
for (List<Integer> subset : result) {
System.out.println(subset);
}
// Output: [], [1], [1,2], [1,2,3], [1,3], [2], [2,3], [3]
}
}

📝 Example 2: N-Queens Problem

Place N queens on an N×N chessboard so that no two queens attack each other.

NQueens.java
java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import java.util.*;
public class NQueens {
public static List<List<String>> solveNQueens(int n) {
List<List<String>> result = new ArrayList<>();
char[][] board = new char[n][n];
// Initialize board with empty spaces
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
board[i][j] = '.';
}
}
backtrack(board, 0, result);
return result;
}
private static void backtrack(char[][] board, int row,
List<List<String>> result) {
// Base case: placed all queens
if (row == board.length) {
result.add(construct(board));
return;
}
// Try placing queen in each column of current row
for (int col = 0; col < board.length; col++) {
if (isValid(board, row, col)) {
board[row][col] = 'Q'; // Choose
backtrack(board, row + 1, result); // Explore
board[row][col] = '.'; // Backtrack
}
}
}
private static boolean isValid(char[][] board, int row, int col) {
// Check column
for (int i = 0; i < row; i++) {
if (board[i][col] == 'Q') return false;
}
// Check diagonal (top-left)
for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) {
if (board[i][j] == 'Q') return false;
}
// Check diagonal (top-right)
for (int i = row - 1, j = col + 1; i >= 0 && j < board.length; i--, j++) {
if (board[i][j] == 'Q') return false;
}
return true;
}
private static List<String> construct(char[][] board) {
List<String> result = new ArrayList<>();
for (char[] row : board) {
result.add(new String(row));
}
return result;
}
public static void main(String[] args) {
int n = 4;
List<List<String>> solutions = solveNQueens(n);
System.out.println("Solutions for " + n + "-Queens:");
for (List<String> solution : solutions) {
for (String row : solution) {
System.out.println(row);
}
System.out.println();
}
}
}

📝 Example 3: Generate Valid Parentheses

Generate all combinations of n pairs of well-formed parentheses.

GenerateParentheses.java
java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import java.util.*;
public class GenerateParentheses {
public static List<String> generateParenthesis(int n) {
List<String> result = new ArrayList<>();
backtrack("", 0, 0, n, result);
return result;
}
private static void backtrack(String current, int open, int close,
int max, List<String> result) {
// Base case: used all parentheses
if (current.length() == max * 2) {
result.add(current);
return;
}
// Add opening parenthesis if we can
if (open < max) {
backtrack(current + "(", open + 1, close, max, result);
}
// Add closing parenthesis if valid
if (close < open) {
backtrack(current + ")", open, close + 1, max, result);
}
}
public static void main(String[] args) {
int n = 3;
List<String> result = generateParenthesis(n);
System.out.println("Valid parentheses for n=" + n + ":");
for (String s : result) {
System.out.println(s);
}
// Output: ((())), (()()), (())(), ()(()), ()()()
}
}

🔑 Key Points to Remember

  • 1️⃣Three steps: Choose → Explore → Undo (backtrack)
  • 2️⃣Use recursion to explore all possibilities
  • 3️⃣Time Complexity: Usually exponential (O(2^n) or O(n!))
  • 4️⃣Always undo changes after exploring (backtrack!)

💪 Practice Problems

  • • Sudoku Solver
  • • Word Search
  • • Combination Sum
  • • Palindrome Partitioning
  • • Letter Combinations of Phone Number