51.N皇后
按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
n 皇后问题 研究的是如何将 n
个皇后放置在 n×n
的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n
,返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q'
和 '.'
分别代表了皇后和空位。
二、分析
1.本题是一个经典的回溯算法题目,怎么辨别题解需要使用回溯算法呢?
回溯法,一般可以解决如下几种问题:
- 组合问题:N个数里面按一定规则找出k个数的集合
- 切割问题:一个字符串按一定规则有几种切割方式
- 子集问题:一个N个数的集合里有多少符合条件的子集
- 排列问题:N个数按一定规则全排列,有几种排列方式
- 棋盘问题:N皇后,解数独等等
2.回溯法模板
回溯三部曲:
(1)返回值以及参数
返回值一般为void。再来看一下参数,因为回溯算法需要的参数可不像二叉树递归的时候那么容易一次性确定下来,所以一般是先写逻辑,然后需要什么参数,就填什么参数
(2)回溯函数终止条件
什么时候达到了终止条件,一般来说搜到叶子节点了,也就找到了满足条件的一条答案,把这个答案存放起来,并结束本层递归
(3)回溯搜索的遍历过程。
for循环是横向遍历可以理解一个节点有多少个孩子,这个for循环就执行多少次
backtracking(递归)就是纵向遍历,这样就把这棵树全遍历完了,一般来说,搜索叶子节点就是找的其中一个结果了。
总结回溯算法模板如下:
void backtracking(参数) {
if (终止条件) {
存放结果;
return;
}
for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
处理节点;
backtracking(路径,选择列表); // 递归
回溯,撤销处理结果
}
}
3.代码
class Solution {
List<List<String>> res=new ArrayList<>(); //res:最终结果
public List<List<String>> solveNQueens(int n) {
char[][] path=new char[n][n];
for(char[] c: path){ //初始化棋盘
Arrays.fill(c,'.');
}
dfs(n,path,0);
return res;
}
void dfs(int n,char[][] path,int row){
if(row==n){
res.add(toArray(path)); //将棋盘转换成list,添加到res
return;
}
for(int i=0;i<n;i++){
if(check(i,n,path,row)){
path[row][i]='Q';
dfs(n,path,row+1);
path[row][i]='.';
}
}
}
boolean check(int column,int n,char[][] path,int row){
for(int i=0;i<row;i++){ //验证当前列是否有皇后
if(path[i][column]=='Q'){
return false;
}
}
for(int i=row-1,j=column-1;i>=0&&j>=0;i--,j--){ //验证左上角对角线是否有皇后
if(path[i][j]=='Q'){
return false;
}
}
for(int i=row-1,j=column+1;i>=0&&j<n;i--,j++){ //验证右上角对角线是否有皇后
if(path[i][j]=='Q'){
return false;
}
}
return true;
}
List toArray(char[][] path){ //将矩阵转换成list
List<String> list = new ArrayList<>();
for(char[] c:path){
list.add(String.copyValueOf(c));
}
return list;
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/116106.html