leetcode算法题之回溯算法
回溯算法的定义
到达一个节点之后有一些选择,选择一个路径往下走,发现没有不能实现预期结果或者不是最优结果在退回至上一步,选择另外一条路径。(在枚举的过程寻找最优解)
1. 八皇后问题
给定一个数值N,在N X N 的棋盘上然后满足八皇后的条件:任意两个皇后不在同一个行,不在同一个列,也不在任何一个对角线位置上。请你打印出N皇后的所有解法,其中用Q表示位置上是皇后,用“·”表示位置上没有放皇后。
- 解题思路
下面放出一张图,通过这张图片来说明白解题目的思路
看到上面这张图,必然离不开递归的思想在里面:从一个节点下到下面的一个子节点有N中选择,每个子节点处又要执行同样的操作。
所以回溯类问题解体的思路如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| void Backtracking(函数参数表) { if(终止条件) { 存放结果 return; } for(选择:本层集和中的元素也就是当前节点子节点数目) { 处理操作 } Backtrack(新的函数列表); 回溯撤销处理结果 }
|
上面的描述是N皇后进行回溯的过程,主要是先初始化定义一个棋盘结果vector,这个容器可以用来存放N个字符串,每个字符串又有N个字符,而且初始化这个字符串容器的每个内容存放的字符为 ‘·’
1 2
| vector<string> chessboard(n,string(n,'.'));
|
总体的求解问题的思路大致如下:
首先定义目标返回数组 result,中间棋盘数组:chessboard,backtrack()函数声明,重点是内部中传递的参数。
按照回溯算法的核心思想backtrack函数(①判断结束条件②做选择并在选择内判断是否继续往下面一项进行,是否进行继续操作③更新选择与条件,继续backtrack④撤销结果)
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
| class Solution { public: vector<vector<string>> solveNQueens(int n) { vector<vector<string>> result; result.clear(); vector<string> chessboard(n, string(n, '.')); Backtrack(n, 0, chessboard,result); return result;
} private: void Backtrack(int n,int row,vector<string> &chessboard,vector<vector<string>> &result) { if(row==n) { result.push_back(chessboard); return ; } for(int col=0;col<n;col++) { if(IsValid(row,col,chessboard,n)) { chessboard[row][col]='Q'; Backtrack(n,row+1,chessboard,result); chessboard[row][col]='.'; } } } bool IsValid(int row,int col,vector<string> &chessboard,int n) { for(int i=0;i<row;i++) { if(chessboard[i][col]=='Q') return false; } for(int i=row-1,j=col-1;i>=0&&j>=0;i--,j--) { if(chessboard[i][j]=='Q') return false; } for(int i=row-1,j=col+1;i>=0&&j>=0;i--,j++) { if(chessboard[i][j]=='Q') return false; } return true; } };
|
2.计算各个位不同数字的个数
当n=0时,答案就是1,当n>10时,没有必要进行研究,相当于研究到n=10即可
第n个的答案为第n-1个答案再加上那N位的答案