Introduction to Backtracking

Have you ever run into these problems in your daily life?

  • For my luggage lock, what are some of the interesting password combination I can come up with? ๐Ÿ”
  • For my living room, how many possible ways I can rearrange my sofa, table, speakers and TV? ๐Ÿ“บ
  • Or, yes! this is a good one, given a set of liquors and juice, what are possible cocktails I can come up with? ๐Ÿน

Backtracking#

"Backtracking can be defined as a general algorithmic technique that considers searching every possible combination in order to solve a computational problem."

Intuitions of A Backtracking Problem#

  1. The problem is about combinations, combinatorics, and permutation. Usually the problem has multiple possible solutions and it asks you to "list" or "enumerate" all the possible solutions.
  2. When you try to come up with an combination of both iteration and recursion. For example, you need to have a loop inside of a recursive function, and the loop's range depends on the function parameters:
void someRecursiveFunction(int x, int y){
/* do something... */
for(int i = 0; i < y; i++){
/* do something in the for loop... */
// call someRecursiveFunction with updated parameters
someRecursiveFunction(x, y+i);
}
/* do something else... */
}
  1. When you can prove that the solution needs a runtime of

Backtracking Generalized Solution Template#

class Solution {
/* Declare private data structures: */
private ArrayList<Integer> solutions;
public List<List<Integer>> permute(int[] nums) {
// declare private data structures
solutions = new ArrayList<>();
// call backtrack
backtrack(param1, param2);
// return results
return this.results;
}
private void backtrack(int param1, int param2){
// handle base case!
if(BaseCase qualified){
// Add current result to the solution collection
solutions.add(param2)
return;
}
for(int i = 0; i< param1; i++){
// 1. Handle edge case
if(count[i] == 0) continue;
// 2. Prepare a possible solution using some variable
result.set(level, nums[i]);
// 3. Remove used variable in step 2
count[i]--;
// 4. Call backtrack recursively
backtrack(param1, param2+1);
// 5. Add used variable in step 2 and 4 back to the set
count[i]++;
}
}
}

References#