回溯算法的框架 解决一个回溯问题,实际上就是一个决策树的遍历过程。你只需要思考 3 个问题:
1、路径:也就是已经做出的选择。
2、选择列表:也就是你当前可以做的选择。
3、结束条件:也就是到达决策树底层,无法再做选择的条件。
如果你不理解这三个词语的解释,没关系,我们后面会用「全排列」和「N皇后问题」这两个经典的回溯算法问题来帮你理解这些词语是什么意思,现在你先留着印象。
代码方面,回溯算法的框架:
1 2 3 4 5 6 7 8 9 10 result = [] def  backtrack (路径, 选择列表 ):    if  满足结束条件:         result.add(路径)         return           for  选择 in  选择列表:         做选择         backtrack(路径, 选择列表)         撤销选择 
其核心就是 for 循环里面的递归,在递归调用之前「做选择」,在递归调用之后「撤销选择」,特别简单。
全排列问题 Leetcode:46.全排列 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 vector<vector<int >> ret; void  backtrack (vector<int > &path, vector<int > &nums)          if  (path.size () == nums.size ())     {         ret.push_back (path);         return ;     }     for  (int  num : nums)     {                           if  (find (path.begin (), path.end (), num) != path.end ())         {             continue ;         }                  path.push_back (num);                  backtrack (path, nums);                  path.pop_back ();     } } vector<vector<int >> permute (vector<int >& nums)  {     vector<int > path;     backtrack (path, nums);     return  ret; } 
N 皇后问题 N 皇后 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 vector<vector<string>> res; vector<vector<string>> solveNQueens (int  n) {          vector<string> board (n, string(n, '.' ))  ;     backtrack (board, 0 );     return  res; } void  backtrack (vector<string>& board, int  row)           if  (row == board.size ())      {         res.push_back (board);         return ;     }          for  (int  col = 0 ; col < board[row].size (); col++)      {                  if  (!isValid (board, row, col))              continue ;                  board[row][col] = 'Q' ;                  backtrack (board, row + 1 );                  board[row][col] = '.' ;     } } bool  isValid (vector<string>& board, int  row, int  col)     int  n = board.size ();          for  (int  i = 0 ; i <= row; i++) {         if  (board[i][col] == 'Q' )             return  false ;     }          for  (int  i = row - 1 , j = col + 1 ;              i >= 0  && j < n; i--, j++) {         if  (board[i][j] == 'Q' )             return  false ;     }          for  (int  i = row - 1 , j = col - 1 ;             i >= 0  && j >= 0 ; i--, j--) {         if  (board[i][j] == 'Q' )             return  false ;     }     return  true ; } 
字母大小全排列 784. 字母大小写全排列 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 vector<string> ret; void  backtrack (string path, string S)     if  (path.size () == S.size ())     {         ret.push_back (path);         return ;     }     char  c = S[path.size ()];     path += c;     backtrack (path, S);          if  (isalpha (c))     {                  path = path.substr (0 , path.size ()-1 );                  if  (c >= 'A'  && c <= 'Z' )         {             path += tolower (c);         }         else              {             path += toupper (c);         }         backtrack (path, S);     } } vector<string> letterCasePermutation (string S)       ret = {};     if  (S.size () == 0 ) return  ret;     string path;     backtrack (path, S);     return  ret; } 
参考