力扣打卡:51. N 皇后
解题思路
用数组来代替字符串数组
回溯算法的框架
List<T> track = new LinkedList<>();
List<List<T>> res = new ArrayList<>();
public void backtrack(){
if(终止条件) {
记录结果
return;
}
for(所有的可能){
1. 做结果
2. backtrack();
3. 撤销选择
}
}
N皇后是指不能在同行同列同斜杠
遇到了遇到求出所有的可能, 但是无子问题的重叠, 那么需要用的就是暴力求解, 也就是使用回溯
按照框架去凑,大的方向就不会错
回溯
就是 N 叉树的遍历
, 做出选择
,然后进行下一个递归
,再进行撤销选择
终止条件
是给定的边界,如 数组索引不越界 等
代码
class Solution {
List<String> track = new LinkedList<>();
List<List<String>> res = new LinkedList<>();
public List<List<String>> solveNQueens(int n) {
// 列出所有的可能 / 得到所有的结果集 没有子问题的分解 -- > 暴力求解 -- > 回溯算法
// Java中的字符操作实在是有点麻烦,用整数数组来代替
int[][] board = new int[n][n];
backtrack(board, 0); // 从 第 0 行开始
return res;
}
// 首先写出终止条件
// 判断终止条件的流程, 回溯就是递归, 多出了做选择的流程
// 当遍历到叶子节点的时候就加入结果集,也就是终止条件
// 也就是从根结点出发(第一行)到叶子节点(最后一行)的,到最后一行那么就是叶子节点了,一行一行的判断穷举
// 如果超出了最后一行,那么说明这肯定是一个可行解,因为最后一行都做出选择了(如果不满足,会直接跳过,而不是做选择)
public void backtrack(int[][] board, int i){
if(i==board.length) { // 如果已经超出了索引,那么说明此时的结果是一个可行解
res.add(new LinkedList<>(track));
return ;
}
StringBuilder line = new StringBuilder(); // 记录每一行的数据
for(int j=0; j<board[i].length; j++){
if(!isValid(board, i, j)) { // 检查同行同列同斜杠是否有皇后,如果无效,那么跳过
line.append("."); // 跳过当前的棋格,也就是 "."
continue;
}
line.append("Q");// 做出选择,也即是此时的位置加入皇后
board[i][j] = 1;
while(line.length() < board[i].length) line.append("."); // 此时的位置不一定是最后一列,那么需要加入空棋格
track.add(line.toString()); // 加入
backtrack(board, i+1); // 传递下一行,因为不能同行同列同斜杠
track.remove(track.size()-1); // 撤销最后一个
board[i][j] = 0;
line.setLength(line.indexOf("Q"));// 找到Q的位置,撤销选择
line.append("."); // 将此时的位置重新加入空棋格
}
}
public boolean isValid(int[][] board, int i, int j){
// 检查同行
for(int y=0; y<board[i].length; y++) if(board[i][y] == 1) return false;
// 检查同列
for(int x=0; x<board.length; x++) if (board[x][j] == 1) return false;
// 检查左上方
for(int x=i-1,y=j-1; x>=0 && y>=0; x--, y--){
if(board[x][y]==1) return false;
}
// 检查右上方
for(int x=i-1,y=j+1; x>=0 && y<board[x].length; x--, y++){
if(board[x][y] == 1) return false;
}
// 不用检查左下方和右下方,因为是按照一行一行的进行穷举,下方还是空棋格,所以不需要检查
// 当然检查了也没事,但是会增加时间复杂度
return true;
}
}