Backtracking solve Subset/Combination/Permutation

Jul 4, 2023

Backtracking is a general algorithmic technique that is used to solve a variety of problems that involve searching through all possible solutions to find the best one.

Backtracking template:

result = []

def backtrack(Path, Seletion List):
    if meet the End Conditon:
        result.add(Path)
        return

    for seletion in Seletion List:
        select
        backtrack(Path, Seletion List)
        deselect

Can be used to solve these common problems:

1. Subset (Leetcode 78)

Input: nums = [1,2,3]

Output: [[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]

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

2. Combination (Leetcode 77)

Input: n = 4, k = 2

Output: [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]

var combine = function (n, k) {
  const res = [];
  var backtrack = function (track, start) {
    if (track.length === k) {
      res.push([...track]);
      return;
    }
    for (let i = start; i < n; i++) {
      track.push(i + 1);
      backtrack(track, i + 1);
      track.pop();
    }
  };
  backtrack([], 0);
  return res;
};

3. Permutation (Leetcode 46)

Input: nums = [1,2,3]

Output: [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

var permute = function (nums) {
  let res = [];
  var backtrack = function (track) {
    // goal
    if (track.length === nums.length) {
      res.push([...track]);
      return;
    }
    for (let i = 0; i < nums.length; i++) {
      if (track.includes(nums[i])) {
        continue;
      }
      track.push(nums[i]);
      backtrack(track);
      track.pop();
    }
  };
  backtrack([]);
  return res;
};

4. Generate Parentheses (Leetcode 22)

Input: n = 3

Output: ["((()))","(()())","(())()","()(())","()()()"]

var generateParenthesis = function(n) {
    const res = [];
    var backtrack = function(track, open, close) {
        console.log(track);
        if (track.length === n*2) {
            res.push(track);
            return;
        }
        if (open < n) {
            backtrack(track + "(", open+1, close)
        }
        if (close < open) {
            backtrack(track + ")", open, close+1)
        }
    }
    backtrack([], 0, 0);
    return res;
};

5. Combination Sum (Leetcode 39)

Input: candidates = [2,3,6,7], target = 7 Output: [[2,2,3],[7]]

var combinationSum = function(candidates, target) {
    const res = [];
    const backtrack = function(track, start, sum) {
        if (sum === target) {
            res.push([...track]);
            return;
        }
        for (let i = start; i < candidates.length; i++) {
            if (sum + candidates[i] > target) {
                continue;
            }
            backtrack([...track, candidates[i]], i, sum + candidates[i])
        }
    }
    backtrack([], 0, 0);
    return res;
};

6. Word Search (Leetcode 79)

Input: board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED" Output: true

Word Search problem

var exist = function (board, word) {
    const rows = board.length;
    const cols = board[0].length;

    var backtrack = function (index, x, y) {
        // meet the target
        if (index === word.length) {
            return true;
        }

        if (x >= cols || x < 0 || y >= rows || y < 0 || board[y][x] !== word[index]) return false;

        const temp = board[y][x];
        board[y][x] = "#";

        const found = backtrack(index + 1, x + 1, y)
        || backtrack(index + 1, x, y - 1)
        || backtrack(index + 1, x, y + 1)
        || backtrack(index + 1, x - 1, y);

        // restore;
        board[y][x] = temp;

        return found;
    }

    for (let i = 0; i < rows; i++) {
        for (let j = 0; j < cols; j++) {
            if (board[i][j] === word[0] && backtrack(0, j, i)) {
                return true;
            }
        }
    }

    return false;
};

Refs:

https://labuladong.gitbook.io/algo-en/iii.-algorithmic-thinking/subset_permutation_combination