按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
n 皇后问题 研究的是如何将 n
个皇后放置在 n×n
的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n
,返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q'
和 '.'
分别代表了皇后和空位。
示例 1:
输入:n = 4 输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]] 解释:如上图所示,4 皇后问题存在两个不同的解法。
示例 2:
输入:n = 1 输出:[["Q"]]
提示:
1 <= n <= 9
N皇后问题在回溯问题中算是相对比较难的,因为其中的递归调用自有妙招。但是一旦掌握其中的奥妙,求解这类问题将会变得非常简单。返回的类型是双重List,每一个List存储一个棋盘。因此我们可以首先在初始化时将所有元素初始化成 . 。注意题目中所说的每个皇后的移动方式是横向,纵向以及斜向45和135度,根据这个条件我们可以创建出检查函数,传入当前坐标i,j,返回能否在当前位置插入。以下是检查函数代码:
public boolean check(int i,int j,char[][] chs){
for(int row = 0;row<i;row++){
if(chs[row][j] == 'Q') return false;
}
for(int row=i-1,col=j-1;row>=0&&col>=0;row--,col--){
if(chs[row][col] == 'Q') return false;
}
for(int row=i-1,col=j+1;row>=0 && col<chs.length;row--,col++){
if(chs[row][col]=='Q') return false;
}
return true;
}
为什么没有检查同一行是否有被占用的情况?这个问题会在下面递归调用中揭晓。
重头戏便是我们的递归调用函数了: 传入参数chs表示当前棋盘,h表示当前横坐标,n表示棋盘大小n。递归方式是通过判断该行的这个元素能否插入元素i,若可以就改为Q插入。然后递归调用下一行。这是因为每一行最多只有一个皇后,因此这一列成功插入后就无需看后面的元素了。这也是为什么不用判断列的原因。
public void backtracking(char[][] chs, int h, int n){
if(h == n){
ans.add(new LinkedList<>(tans));
return;
}
for(int i=0;i<n;i++){
if(check(h,i,chs)){
chs[h][i] = 'Q';
tans.add(new String(chs[h]));
backtracking(chs,h+1,n);
chs[h][i] = '.';
tans.remove(tans.size()-1);
}
}
}
以上便是核心代码。整体代码如下:
class Solution {
List<List<String>> ans = new LinkedList<>();
List<String> tans = new LinkedList<>();
char[][] chs;
public List<List<String>> solveNQueens(int n) {
chs = new char[n][n];
for(char[] t : chs){
for(int c=0;c<n;c++){
t[c] = '.';
}
}
backtracking(chs,0,n);
return ans;
}
public void backtracking(char[][] chs, int h, int n){
if(h == n){
ans.add(new LinkedList<>(tans));
return;
}
for(int i=0;i<n;i++){
if(check(h,i,chs)){
chs[h][i] = 'Q';
tans.add(new String(chs[h]));
backtracking(chs,h+1,n);
chs[h][i] = '.';
tans.remove(tans.size()-1);
}
}
}
public boolean check(int i,int j,char[][] chs){
for(int row = 0;row<i;row++){
if(chs[row][j] == 'Q') return false;
}
for(int row=i-1,col=j-1;row>=0&&col>=0;row--,col--){
if(chs[row][col] == 'Q') return false;
}
for(int row=i-1,col=j+1;row>=0 && col<chs.length;row--,col++){
if(chs[row][col]=='Q') return false;
}
return true;
}
}