Backtracking algorithm, there are many kinds of algorithm questions in Leetcode, combined with a few Leecode questions, deepen the understanding of this, convenient to brush questions happily in the future.
Backtracking algorithm
concept
Backtracking, or DFS, when you see depth-first, what do you think? Is the tree traversal, one path to black, and then back to the previous step, is a tentative algorithm. And the way to do it, let me just say it, is recursively.
sample
To illustrate:
Leetcode Restores the iP address
Given a string containing only numbers, undo it and return all possible IP address formats. IP addresses have the following characteristics:
- 4 integers (each integer between 0 and 255)
- You can’t start with zero, but you can have one zero
- Integers are separated by ‘.’
So let me just draw a tree diagram of it, and usually when I do backtracking, I just draw a graph.
It can be seen that the backtracking algorithm is actually a depth-first search attempt process similar to enumeration, which is mainly to find the solution of the problem during the search attempt. When it is found that the solution condition is not met, it will “backtrack” back (that is, recursive return) and try other paths.
The problem solving
As mentioned earlier, since the backtracking algorithm uses recursion, LET me use recursion to solve this problem:
var restoreIpAddresses = function(s) {
let res = [];
dfs(s, 1, -1[]);/** * backtracking algorithm *@param {*} The string * passed in by STR@param {*} Level Indicates the number of an IP address. The value starts from 0 *@param {*} Index The position of the string to be selected *@param {*} IpAddress Indicates the IP address. The value is entered as an array. Connect. For example, [192, 168, 80, 1] can be connected to 192.168.80.1 */
function dfs(str, level, index, ipAddress) {
//1. Cut-off conditions
if(level === 5 || index === str.length -1) {if(level === 5 && index === str.length -1){
res.push(ipAddress.join('. '));
}
return;
}
// 2. Candidate node
// Each integer is between 0 and 255, with the first three digits at most
for(let i =1; i <4; i++){
let ip = str.substr(index+1, i);
// Check whether conditions ranging from 0 to 255 are met. The value cannot start with 0
if(parseInt(ip)<256 && ( ip === '0'| |! ip.startsWith('0'))){
ipAddress.push(ip);
dfs(str,level+1,index+i,ipAddress); ipAddress.pop(); }}}return res;
}
Copy the code
The problem solving template
- Determine the recursive termination condition
- Find the candidate node to push
- Pop out the data after completing the recursion, called backtracking
This is just a template for how I think to solve this kind of problem.
Backtracking problem solving
The main brush a few leecode topic to deepen their understanding, are set above the template
A combination of letters for a telephone number
Telephone number alphabetic combination
/ * * *@param {string} digits
* @return {string[]}* /
var letterCombinations = function(digits) {
// Handle boundary conditions
if(digits.length<1) {return[]}let res=[];
// Create a map data structure to store numbers and letters
let map = new Map()
.set('2'.'abc')
.set('3'.'def')
.set('4'.'ghi')
.set('5'.'jkl')
.set('6'.'mno')
.set('7'.'pqrs')
.set('8'.'tuv')
.set('9'.'wxyz');
dfs(digits, 0 , ' ');
/** * digits: string passed in * index: number traversed * STR: combination of letters */
function dfs(digits, index, str){
//1. Cut-off conditions
if(index === digits.length){
res.push(str);
return;
}
// 2. Candidate node
for(let s of map.get(digits[index])){
str+= s;
dfs(digits, index+1,str);
// 3. Backtrace, pop from stack
str= str.slice(0, str.length-1); }}return res;
};
Copy the code
The total number of combinations
The total number of combinations
/ * * *@param {number[]} candidates
* @param {number} target
* @return {number[][]}* /
var combinationSum = function(candidates, target) {
let res = [];
let strArr = [];
dfs(candidates, target, []);
function dfs(candidates, remain, arr){
if(remain <= 0) {if(remain === 0) {let str = [...arr].sort(function(a,b) {
return a-b;
});
// This is mainly about de-weighting
if(strArr.indexOf([...str].toString()) === -1){ strArr.push([...str].toString()); res.push([...str]); }}return;
}
for(let can ofcandidates){ remain -= can; arr.push(can); dfs(candidates, remain, arr); remain+=can; arr.pop(); }}return res;
};
Copy the code