题目地址:LeetCode 51.N皇后
1.问题思路
N皇后问题是一道典型的回溯思想题,知题意,对于N*N的网格中找出满足条件的皇后布局。
- 递归方法
dfs(char[][] charry, int row),row用来标识当前深度,所有的结果都存储在全局遍历result。 - 确定递归终止条件
① row = n, 代表到达了最后一行,剪枝。
② 同行,同列,斜对角线(45°,135°)存在皇后,剪枝。 - 每层遍历的集合,即【0, col-1】
这里需要遍历的深度即是棋盘的行数,每层遍历的长度即是棋盘的列数。所以我们从行数开始遍历,进行放置皇后(需要满足垂直,斜对角不能存在皇后)如果不满足则进行回溯。
2.代码实现
class Solution {
int n = 0;
List<List<String>> result = new ArrayList<>();
public List<List<String>> solveNQueens(int n) {
this.n = n;
char[][] chess = new char[n][n];
for (int i = 0; i < chess.length; i++) {
Arrays.fill(chess[i], '.');
}
dfs(chess, 0);
return result;
}
/**
* 首先整个棋盘都是空棋盘,没有皇后的。
* 其次我们需要对每一行进行放置一个皇后(
* 限制1: 同行不能存在
* 限制2: 同列不能存在
* 限制3: 写对角线不能存在(45° 135°)
* )
* 这是一道典型的回溯算法, dfs的深度为数的行数, 每层集合是棋盘的列数
*/
public void dfs(char[][] charry, int row) {
// 到达最后一行
if (row == n) {
// 添加到结果集
append(charry);
return;
}
// 遍历每列
for (int i = 0; i < charry[row].length; i++) {
if (!valid(charry, row, i)) {
continue;
}
charry[row][i] = 'Q';
dfs(charry, row+1);
charry[row][i] = '.';
}
}
public void append(char[][] charry){
List<String> list = new ArrayList<>();
for (char[] c : charry) {
list.add(String.copyValueOf(c));
}
result.add(list);
}
public boolean valid(char[][] charry, int row, int col) {
// 同列不能存在皇后
for (int i = 0; i < row; i++) {
if (charry[i][col] == 'Q') {
return false;
}
}
// 45°不能存在皇后
for (int i = row-1, j = col-1; i >=0 && j>=0; i--, j--) {
if (charry[i][j] == 'Q') {
return false;
}
}
// 135°不能存在皇后
for (int i=row-1, j=col+1; i>=0&&j<=n-1; i--, j++) {
if (charry[i][j] == 'Q') {
return false;
}
}
// 这里不用遍历当前行是不是存在,因为从dfs来看 同行不存在皇后
return true;
}
}