Backtracking Problems

N-Queens Problem

function solveNQueens(n) {
    let result = [];
    let board = new Array(n).fill().map(() => new Array(n).fill('.'));
    let cols = new Array(n).fill(false), diag1 = new Array(2*n - 1).fill(false), diag2 = new Array(2*n - 1).fill(false);

    function backtrack(row) {
        if (row === n) {
            result.push(board.map(r => r.join('')));
            return;
        }
        for (let col = 0; col < n; col++) {
            if (cols[col] || diag1[row - col + n - 1] || diag2[row + col]) continue;
            board[row][col] = 'Q';
            cols[col] = diag1[row - col + n - 1] = diag2[row + col] = true;
            backtrack(row + 1);
            board[row][col] = '.';
            cols[col] = diag1[row - col + n - 1] = diag2[row + col] = false;
        }
    }

    backtrack(0);
    return result;
}
        

Sudoku Solver

function solveSudoku(board) {
    function isValid(board, row, col, num) {
        for (let i = 0; i < 9; i++) {
            if (board[row][i] === num || board[i][col] === num) return false;
            if (board[Math.floor(row / 3) * 3 + Math.floor(i / 3)][Math.floor(col / 3) * 3 + i % 3] === num) return false;
        }
        return true;
    }
    
    function backtrack(board) {
        for (let row = 0; row < 9; row++) {
            for (let col = 0; col < 9; col++) {
                if (board[row][col] === '.') {
                    for (let num = 1; num <= 9; num++) {
                        if (isValid(board, row, col, num.toString())) {
                            board[row][col] = num.toString();
                            if (backtrack(board)) return true;
                            board[row][col] = '.';
                        }
                    }
                    return false;
                }
            }
        }
        return true;
    }
    
    backtrack(board);
}
        

Find All Subsets of a Set (Power Set)

function subsets(nums) {
    let result = [];
    function backtrack(start, current) {
        result.push([...current]);
        for (let i = start; i < nums.length; i++) {
            current.push(nums[i]);
            backtrack(i + 1, current);
            current.pop();
        }
    }
    backtrack(0, []);
    return result;
}
        

Generate All Permutations of a String

function permute(nums) {
    let result = [];
    function backtrack(start) {
        if (start === nums.length) {
            result.push([...nums]);
            return;
        }
        for (let i = start; i < nums.length; i++) {
            [nums[start], nums[i]] = [nums[i], nums[start]]; // Swap
            backtrack(start + 1);
            [nums[start], nums[i]] = [nums[i], nums[start]]; // Backtrack
        }
    }
    backtrack(0);
    return result;
}
        

Generate All Combinations of a Set

function combine(n, k) {
    let result = [];
    function backtrack(start, current) {
        if (current.length === k) {
            result.push([...current]);
            return;
        }
        for (let i = start; i <= n; i++) {
            current.push(i);
            backtrack(i + 1, current);
            current.pop();
        }
    }
    backtrack(1, []);
    return result;
}
        

Solve the Rat in a Maze Problem

function solveMaze(maze, start, end) {
    let N = maze.length;
    let result = [];
    let visited = Array.from({length: N}, () => Array(N).fill(false));

    function backtrack(x, y, path) {
        if (x === end[0] && y === end[1]) {
            result.push([...path]);
            return;
        }
        if (x < 0 || y < 0 || x >= N || y >= N || maze[x][y] === 0 || visited[x][y]) return;
        visited[x][y] = true;
        path.push([x, y]);

        backtrack(x + 1, y, path);
        backtrack(x - 1, y, path);
        backtrack(x, y + 1, path);
        backtrack(x, y - 1, path);

        path.pop();
        visited[x][y] = false;
    }

    backtrack(start[0], start[1], []);
    return result;
}
        

Find the Hamiltonian Path in a Graph

function hamiltonianPath(graph, start) {
    let N = graph.length;
    let visited = Array(N).fill(false);
    let path = [];

    function backtrack(v) {
        path.push(v);
        visited[v] = true;
        
        if (path.length === N) return true;
        for (let i = 0; i < N; i++) {
            if (graph[v][i] === 1 && !visited[i]) {
                if (backtrack(i)) return true;
            }
        }
        
        visited[v] = false;
        path.pop();
        return false;
    }

    return backtrack(start) ? path : [];
}
        

Subset Sum Problem Using Backtracking

function subsetSum(nums, target) {
    let result = [];
    function backtrack(start, currentSum, current) {
        if (currentSum === target) {
            result.push([...current]);
            return;
        }
        if (currentSum > target) return;
        for (let i = start; i < nums.length; i++) {
            current.push(nums[i]);
            backtrack(i + 1, currentSum + nums[i], current);
            current.pop();
        }
    }
    backtrack(0, 0, []);
    return result;
}
        

Word Search in a 2D Matrix

function exist(board, word) {
    let m = board.length, n = board[0].length;

    function dfs(i, j, index) {
        if (index === word.length) return true;
        if (i < 0 || j < 0 || i >= m || j >= n || board[i][j] !== word[index]) return false;

        let temp = board[i][j];
        board[i][j] = '#'; // Mark as visited

        let res = dfs(i + 1, j, index + 1) || dfs(i - 1, j, index + 1) ||
                 dfs(i, j + 1, index + 1) || dfs(i, j - 1, index + 1);

        board[i][j] = temp; // Restore
        return res;
    }

    for (let i = 0; i < m; i++) {
        for (let j = 0; j < n; j++) {
            if (dfs(i, j, 0)) return true;
        }
    }

    return false;
}
        

Combination Sum

function combinationSum(candidates, target) {
    let result = [];
    function backtrack(start, currentSum, current) {
        if (currentSum === target) {
            result.push([...current]);
            return;
        }
        if (currentSum > target) return;
        for (let i = start; i < candidates.length; i++) {
            current.push(candidates[i]);
            backtrack(i, currentSum + candidates[i], current);
            current.pop();
        }
    }
    backtrack(0, 0, []);
    return result;
}
        

Palindrome Partitioning

function partition(s) {
    let result = [];
    function backtrack(start, current) {
        if (start === s.length) {
            result.push([...current]);
            return;
        }
        for (let end = start + 1; end <= s.length; end++) {
            let sub = s.slice(start, end);
            if (sub === sub.split('').reverse().join('')) {
                current.push(sub);
                backtrack(end, current);
                current.pop();
            }
        }
    }
    backtrack(0, []);
    return result;
}
        

All Possible Expressions for a Given Value

function diffWaysToCompute(input) {
    let result = [];
    
    function calculate(left, right, op) {
        if (op === '+') return left + right;
        if (op === '-') return left - right;
        if (op === '*') return left * right;
    }
    
    for (let i = 0; i < input.length; i++) {
        if (['+', '-', '*'].includes(input[i])) {
            let left = diffWaysToCompute(input.slice(0, i));
            let right = diffWaysToCompute(input.slice(i + 1));
            
            for (let l of left) {
                for (let r of right) {
                    result.push(calculate(l, r, input[i]));
                }
            }
        }
    }
    
    if (result.length === 0) result.push(Number(input));
    return result;
}