n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
上图为 8 皇后问题的一种解法。
给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。
每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。
示例:
输入: 4
输出: [
[".Q..", // 解法 1
"...Q",
"Q...",
"..Q."],
["..Q.", // 解法 2
"Q...",
"...Q",
".Q.."]
]
解释: 4 皇后问题存在两个不同的解法。
解题思路:利用四个辅助数组line[n]、col[n]、left[2n-1]、right[2n-1],分别记录第i行、第i列、从上往下数第i条左斜线、从上往下数第i条右斜线是否有皇后,左右斜线下标i与元素下标[h, l]的关系如下图(右斜线是将计算结果取绝对值):
然后进行深度优先搜索
java代码:
class Solution {
public List> solveNQueens(int n) {
boolean[] line = new boolean[n];//line[i]记录第i行是否有皇后
boolean[] col = new boolean[n];//col[i]记录第i列是否有皇后
boolean[] leftDiagonal = new boolean[2*n-1];//leftDiagonal[i]记录从上往下数第i条左斜对角线是否有皇后
boolean[] rightDiagonal = new boolean[2*n-1];//rightDiagonal[i]记录从上往下数第i条右斜对角线是否有皇后
char[][] tmp = new char[n][n];
for(int i = 0; i < n; i++){
for(int j = 0; j < n;j++)
tmp[i][j] = '.';
}
List> res = new LinkedList<>();
dfs(tmp,0, 0, res, line, col, leftDiagonal, rightDiagonal);
return res;
}
private void dfs(char[][] hang, int s, int queen, List> res, boolean[] line, boolean[] col, boolean[] left, boolean[] right){
int n = line.length;
for(; s < n*n; s++){
int h = s/n, l = s%n;
if(line[h] || col[l] || left[h+l] || right[Math.abs(l-h-(n-1))]){
continue;
}
hang[h][l] = 'Q';
queen++;
line[h] = true;
col[l] = true;
left[h+l] = true;
right[Math.abs(l-h-(n-1))] = true;
dfs(hang, s+1, queen, res, line, col, left, right);
hang[h][l] = '.';
queen--;
line[h] = false;
col[l] = false;
left[h+l] = false;
right[Math.abs(l-h-(n-1))] = false;
}
if(n == queen){
List tmp = new ArrayList<>(4);
for(int i = 0; i < n; i++){
tmp.add(new String(hang[i]));
}
res.add(tmp);
}
}
}
注:该种解法运行效率较慢(130ms),但是目前未想到好的优化思路,后续如果有做算法优化,会更新此文。