前言
什么是皇后
- 就是一个排列程序
- 0~N行,每一行选取一个列,每个列不能重复(解决皇后行列之间攻击问题)
- 在上面基础上,在限制上对角线不可以重复。其实就是排列加上了限制条件。
题目细节
对角线是什么,如何判断对角线是否会攻击到呢,也就是如何判断对角线的限制条件
关于 \ 对角线
- 这条对角线的,行号减列号是相等的,也就是x-y是相等的。
-
关于 / 对角线
这条对角线的,行号加列号是相等的,也就是x+y是相等的。
-
�代码实现,完整注释
class Solution {
//存一下数字n,省着下传了
private int n;
//记录一个列号是否用过
private Map<Integer,Boolean> columnUsed = new HashMap<>();
//记录一个左\对角线的值是否用过.row - col
private Map<Integer,Boolean> leftDiagonalUsed = new HashMap<>();
//记录一个右/对角线的值是否用过 row + col
private Map<Integer,Boolean> rightDiagonalUsed = new HashMap<>();
//记录当前的选择列
private List<Integer> chosen = new ArrayList<>();
//我们的最终要返回的答案,未格式化版本
private List<List<Integer>> answer = new ArrayList<>();
public List<List<String>> solveNQueens(int n) {
//保存n
this.n = n;
//执行DFS
dfs(0);
//格式化的result
List<List<String>> result = new ArrayList<>();
//这一层循环,每一次循环代表的是一个棋牌的摆放方式
for(List<Integer> oneAnswer : answer){
//这一次循环代表的是,一个棋盘的一行的Q的位置
List<String> oneResult = new ArrayList<>();
for(Integer qIndex : oneAnswer){
//首先用一个char数组表示一行,然后全填满.
char[] row = new char[n];
Arrays.fill(row, '.');
row[qIndex] = 'Q';
String oneRowResult = new String(row);
oneResult.add(oneRowResult);
}
result.add(oneResult);
}
return result;
}
public void dfs(Integer row){
//递归终止条件。当0~(n-1)行都放完了,到n了就终止了
if(row == n){
answer.add(new ArrayList<>(chosen));
return;
}
//写核心逻辑,在一行中,考虑所有列,放在那一列上。
//也就是在0~(n-1)列中选一列没有用过的
for(int column = 0; column < n; column++){
//如果:1.这一列没有被用过 2.左右对角线都是可以使用的
if(!columnUsed.getOrDefault(column,false) && !leftDiagonalUsed.getOrDefault(row - column,false) && !rightDiagonalUsed.getOrDefault(row + column,false)){
//使用当前列,放入选择
chosen.add(column);
//记录该列为已使用
columnUsed.put(column,true);
//记录当前左右对角线为已使用。
leftDiagonalUsed.put(row - column,true);
rightDiagonalUsed.put(row + column,true);
//这一行已经放完了,去放下一行
dfs(row +1);
//都放完了要还原现场。回溯!
//设置列使用为false,变为没使用过
columnUsed.put(column,false);
//设置左右对角线未使用
leftDiagonalUsed.put(row - column,false);
rightDiagonalUsed.put(row + column,false);
//当前选择里把放在末尾的这一列去掉
chosen.remove(chosen.size()-1);
}
}
}
}