题目描述
按照国际象棋的规则,
皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
n
皇后问题 研究的是
- 如何将
n
个皇后放置在n*n
的棋盘上 - 并且使皇后彼此之间不能相互攻击
给你一个整数 n
,返回所有不同的 n
皇后问题 的解决方案。
每一种解法包含一个不同的 n
皇后问题 的棋子放置方案
该方案中 'Q'
和 '.'
分别代表了皇后和空位。
示例1
示例2
输入:n = 1
输出:[["Q"]]
提示
1 <= n <= 9
题目解析
- 明确题目要求
- 给定的参数有
n
: 表示n
个皇后,需要放置在n*n
的棋盘上 - 并且保证 皇后 之间彼此不能互相攻击
- 皇后攻击规则:同一行或同一列或同一斜线上的棋子
- 很显然,需要穷举每一种可能
- 然后统计保存符合题目要求的结果
- 尝试把第一个皇后放置在第一个位置,坐标
[0, 0]
---- - 这里理解错误,因为行互斥,所以应该是尝试第一行放置皇后
- 然后标记一下被放置的位置,以及可能被攻击的位置
- 然后尝试在下一行 放置 下一个皇后
- 直到所有的皇后被放置完
- 把符合条件的方案添加到结果集中
show code
class Solution {
// 创建结果集
private List<List<String>> ans;
public List<List<String>> solveNQueens(int n) {
// 初始化结果集
ans = new ArrayList<>();
// 创建一个二维矩阵,来标识保存皇后被放置的位置
char[][] chessboard = new char[n][n];
// 初始化棋盘的值
for (char[] chars : chessboard) {
Arrays.fill(chars, '.');
}
// 进入回溯,棋盘 和 当前的行
bt(chessboard, 0);
return ans;
}
private void bt(char[][] chessboard, int row) {
// 如果放置的皇后数等于 n
if (row == chessboard.length) {
toAnswer(chessboard);
return;
}
// 遍历当前行
for (int j = 0; j < chessboard.length; j++) {
if (chessboard[row][j] == '.' && check(row, j, chessboard)) {
// 放置皇后.
chessboard[row][j] = 'Q';
// 回溯
bt(chessboard, row + 1);
// 取消放置的皇后
chessboard[row][j] = '.';
}
}
}
private boolean check(int i, int j, char[][] chessboard) {
// 判断 i j 位置是否满足放置一个皇后的条件
int n = chessboard.length;
// 判断列
for (int k = 0; k < n; k++) {
if (chessboard[k][j] == 'Q') {
return false;
}
}
// i--,j++ 右上方
for (int i1 = i - 1, j1 = j + 1; i1 >= 0 && j1 < n; i1--, j1++) {
if (chessboard[i1][j1] == 'Q') {
return false;
}
}
// i--,j-- 左上方
for (int i1 = i - 1, j1 = j - 1; i1 >= 0 && j1 >= 0; i1--, j1--) {
if (chessboard[i1][j1] == 'Q') {
return false;
}
}
return true;
}
private void toAnswer(char[][] chessboard) {
List<String> ret = new ArrayList<>();
for (char[] chars : chessboard) {
StringBuilder builder = new StringBuilder();
for (char aChar : chars) {
builder.append(aChar);
}
ret.add(builder.toString());
}
ans.add(ret);
}
}