51. N皇后
完成
思路:
如何用回溯法搜索二维棋盘是这道题目和之前不一样的地方,也是题目的难点。
在树形结构中,同层取同一行棋盘的不同列遍历。每递归一次就往下遍历一行。
代码
class Solution {
List<List<String>> res = new ArrayList<>();
// 棋盘
char[][] chessboard;
public List<List<String>> solveNQueens(int n) {
chessboard = new char[n][n];
// 初始化棋盘
for (char[] c : chessboard) {
Arrays.fill(c, '.');
}
backTrack(n, 0);
return res;
}
public void backTrack(int n, int row) {
if (row == n) {
// 把合法的棋盘情况添加进去
res.add(Array2List(chessboard));
return;
}
// 同层遍历列
for (int col = 0;col < n; ++col) {
// 判断是否存在同行同列同斜线的棋子
if (isValid (row, col, n, chessboard)) {
chessboard[row][col] = 'Q';
backTrack(n, row+1);
chessboard[row][col] = '.';
}
}
}
public List Array2List(char[][] chessboard) {
List<String> list = new ArrayList<>();
for (char[] c : chessboard) {
list.add(String.copyValueOf(c));
}
return list;
}
public boolean isValid(int row, int col, int n, char[][] chessboard) {
// 检查列
for (int i=0; i<row; ++i) { // 相当于剪枝
if (chessboard[i][col] == 'Q') {
return false;
}
}
// 检查45度对角线
for (int i=row-1, j=col-1; i>=0 && j>=0; i--, j--) {
if (chessboard[i][j] == 'Q') {
return false;
}
}
// 检查135度对角线
for (int i=row-1, j=col+1; i>=0 && j<=n-1; i--, j++) {
if (chessboard[i][j] == 'Q') {
return false;
}
}
return true;
}
}
总结
回溯法就是暴力搜索,并不是什么高效的算法,最多再剪枝一下。
回溯算法能解决如下问题:
- 组合问题:N个数里面按一定规则找出k个数的集合
- 排列问题:N个数按一定规则全排列,有几种排列方式
- 切割问题:一个字符串按一定规则有几种切割方式
- 子集问题:一个N个数的集合里有多少符合条件的子集
- 棋盘问题:N皇后,解数独等等