题目描述
n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。
样例描述
思路
回溯 + 剪枝
- 按行来放置皇后,每行只能放一个。
- 检查当前位置是否可以放。具体检查所在的列,左上的对角线和右上的对角线。不需要检查行,因为每行只有一个。不需要检查左下和右下,这里剪枝了。因为每次放时保证与之前已经放过的不重复,而行是从上往下来的,所以不需要检查左下和右下。
- 检查对角线能否放置时,设置一个增幅变量,每次检查当前位置开始的对角线上的所有元素(保证不出界的情况下)是否存在皇后。只要有一个就返回false
String.valueOf()
能将字符数组转成字符串。
代码
class Solution {
List<List<String>> res = new ArrayList<>();
public List<List<String>> solveNQueens(int n) {
//初始化棋盘
char board[][] = new char[n][n];
for (char[] ch: board) {
Arrays.fill(ch, '.');
}
backTrack(board, 0, n);
return res;
}
public void backTrack(char board[][], int row, int n) {
//按行来放皇后,若等于n说明找到一个棋盘满足
if (row == n) {
List<String> list = new ArrayList<>();
for (int i = 0; i < n; i ++ ) {
//字符数组转化为字符串,一行一行转入到棋盘中
list.add(String.valueOf(board[i]));
}
//棋盘加入结果集
res.add(list);
return;
}
//对于这行的每个位置
for (int j = 0; j < n; j ++ ) {
//如果可以放置,才进行放置和继续下一个
if (check(board, row, j, n)) {
board[row][j] = 'Q';
backTrack(board, row + 1, n);
//恢复现场
board[row][j] = '.';
}
}
}
public boolean check(char board[][], int i, int j, int n ) {
//由于是一行只放一个皇后,所以不需要检查行。 下面检查出现Q就返回false
//检查所在的列
for (int k = 0; k < n; k ++ ) {
if (board[k][j] == 'Q') return false;
}
//下面k都是控制增减的幅度从1开始递增到n
//检查左上方的对角线
for (int k = 1; k < n; k ++ ) {
if (i - k >= 0 && j - k >= 0 && board[i - k][j - k] == 'Q') return false;
}
//检查右上方的对角线
for (int k = 1; k < n; k ++ ) {
if (i - k >= 0 && j + k < n && board[i - k][j + k] == 'Q') return false;
}
return true;
}
}