N queens 同一行,同一列,同一条对角线只能有一个queen。对于N*N的棋盘,有2N-1条 左上-右下 方向的对角线,纵坐标-横坐标是定值,但是可能会有负数;2N-1条 左下-右上 方向的对角线上的点,横坐标+纵坐标是定值。这是一个深度为N的DFS,回溯的时候记得把访问过的列和对角线还原。
一开始写的时候,把找到答案的那个if写到了for循环里面,导致出现重复答案;把if放在dfs的最上面后,加不加return都没有影响。
class Solution {
public List<List<String>> solveNQueens(int n) {
/* 0,0 0,1 0,2
1,0 1,1 1,2
2,0 2,1 2,2
*/
// queenRow[i]表示第i个queen在第i行的第几列
int[] queenRow = new int[n];
// 表示哪些列已经被占用,行不需要,因为一行只放一个queen
boolean[] col = new boolean[n];
// 左下-右上 对角线,横坐标+纵坐标 一定
boolean[] diag1 = new boolean[2 * n - 1];
// 左上-右下 对角线,纵坐标-横坐标 一定,但是会有负数,所以要加n-1
boolean[] diag2 = new boolean[2 * n - 1];
List<List<String>> ans = new ArrayList<>();
putQueen(n, 0, queenRow, col, diag1, diag2, ans);
return ans;
}
private void putQueen(int n, int index, int[] queenRow, boolean[] col, boolean[] diag1, boolean[] diag2, List<List<String>> ans){
if(index == n){
ans.add(generateMap(queenRow));
return;
}
// 这时是第index行,遍历所有列
for(int i = 0; i < n; i++){
if(!col[i] && !diag1[index + i] && !diag2[index - i + n - 1]){
queenRow[index] = i;
col[i] = true;
diag1[index + i] = true;
diag2[index - i + n - 1] = true;
putQueen(n, index+1, queenRow, col, diag1, diag2, ans);
col[i] = false;
diag1[index + i] = false;
diag2[index - i + n - 1] = false;
}
}
}
private List<String> generateMap(int[] queenRow){
int n = queenRow.length;
char[][] map = new char[n][n];
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
if(queenRow[i] == j){
map[i][j] = 'Q';
}else{
map[i][j] = '.';
}
}
}
List<String> ans = new ArrayList<>();
for(int i = 0; i < n; i++){
ans.add(String.valueOf(map[i]));
}
return ans;
}
}