Reference: Qwen3-32B model
Definition
Is a brute force method but smarter. The algorithm will explore all the possibilities recursively and build the solution step by step. When a certain path doesn't work or already complete, it will undo (backtrack) and try another solution.
Core Concept
Think of backtracking as exploring a maze :
- You try a path forward
- If you hit a dead end, you go back and try a different path
- Continue until you find the exit or exhaust all possibilities
Common applications
- Permutation generation
- Sudoku solver
- Subset/Combination Problems
- Maze solving
- N-Queens problem
Examples
Generate permutations of a list [1,2,3]
function permute(nums: number[]): number[] {
function backtrack(path: number[], used: number[]): void {
if (path.length == nums.length) {
result.push([...path]);
return;
}
for(let i = 0; i < nums.length; i++) {
if (!used[i]) {
used[i] = true;
path.push(nums[i]);
backtrack(path, used);
path.pop(); // Undo the last choice
used[i] = false; // Mark as unused for next iteration
}
}
}
let result = [];
let used = new Array(nums.length).fill(false);
backtrack([], used)
}Intuition
- Add current element to path and marked current element as
used. - Continue to explore the possibilities of the current element by recursive call
- Undo the path/pop the element & mark as
unused(backtrack) to explore new possibilites of another element in array - If path contains all elements of
nums, we have a solution. Path is complete.
Decision tree:
Start: []
├── Choose 1 → [1]
│ ├── Choose 2 → [1, 2]
│ │ └── Choose 3 → [1, 2, 3] ✅
│ └── Choose 3 → [1, 3]
│ └── Choose 2 → [1, 3, 2] ✅
├── Choose 2 → [2]
│ ├── Choose 1 → [2, 1]
│ │ └── Choose 3 → [2, 1, 3] ✅
│ └── Choose 3 → [2, 3]
│ └── Choose 1 → [2, 3, 1] ✅
└── Choose 3 → [3]
├── Choose 1 → [3, 1]
│ └── Choose 2 → [3, 1, 2] ✅
└── Choose 2 → [3, 2]
└── Choose 1 → [3, 2, 1] ✅Combination Sum
Given an array of distinct integers
candidatesand a target integertarget, return a list of all unique combinations ofcandidateswhere the chosen numbers sum totarget. You may return the combinations in any order. The same number may be chosen fromcandidatesan unlimited number of times. Two combinations are unique if the frequency of at least one of the chosen numbers is different.
Input: candidates = [2,3,6,7], target = 7 Output: [[2,2,3],[7]]
Intuition:
Since the problem allows to reuse an element multiple times, we can backtrack over and over until the remaining target = 0 or less than 0.
In each backtrack, we decrement the remaining target by target - candidates[i]:
- If
remainingTarget == 0We have find a combination that sum up totarget - If
remainingTarget < 0. We have not found a combination, return to parent and remove element frompath
Note: The problem allow to reuse elements but dont allow to have duplicate combinations: [2,3,3] and [3,2,2] are the same. So [2,3,3] is enough.
In order to do this, we have to keep track of the currentIndex in our backtrack steps, currentIndex let us explore new combinations while not producing duplicates by skipping the previous elements.
So our backtrack will look like this:
backtrack(path, currentIndex, remainingTarget) {}In each backtrack, we explore combinations by using for to loop through candidates.
The loop is started from currentIndex to use the same element multiple times and prevent using previous elements.
At each iteration, we add currentElement to path and continue to go deeper. After that, we pop the path to try new combinations.