1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
class Solution {
private Set<Integer> rowsWithQueen = new HashSet<>();
private Set<Integer> colsWithQueen = new HashSet<>();
private Set<Integer> diagWithQueen = new HashSet<>();
private Set<Integer> antiWithQueen = new HashSet<>();
private List<List<String>> ans = new ArrayList<>();

public List<List<String>> solveNQueens(int n) {
char[][] board = new char[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
board[i][j] = '.';
}
}
backtrack(board, 0);
return ans;
}

private void backtrack(char[][] board, int row) {
if (row == board.length) {
ans.add(createBoard(board));
return;
}
for (int i = 0; i < board.length; i++) {
if (isValidPosition(row, i)) {
addQueen(row, i);
board[row][i] = 'Q';
backtrack(board, row + 1);
board[row][i] = '.';
removeQueen(row, i);
}
}
}

private boolean isValidPosition(int row, int col) {
return !rowsWithQueen.contains(row) && !colsWithQueen.contains(col) && !diagWithQueen.contains(row - col)
&& !antiWithQueen.contains(row + col);
}

private void addQueen(int row, int col) {
rowsWithQueen.add(row);
colsWithQueen.add(col);
diagWithQueen.add(row - col);
antiWithQueen.add(row + col);
}

private void removeQueen(int row, int col) {
rowsWithQueen.remove(row);
colsWithQueen.remove(col);
diagWithQueen.remove(row - col);
antiWithQueen.remove(row + col);
}

private List<String> createBoard(char[][] board) {
List<String> newBoard = new ArrayList<>();
for (int i = 0; i < board.length; i++) {
String currRow = new String(board[i]);
newBoard.add(currRow);
}
return newBoard;
}
}

N皇后, 很经典的回溯. 关键点在于同一个diagonal线上的row - col的值是定值, 因为往左上或者右下移动, row和col是同时增加的. 因此二者的差相同. 同一个anti- diagonal的线上的row + col是定值, 因为往左下和右上, 一个值增加另一个值减少. 比如去右上的话row减小但是col增加. 这是关键. 然后这道题就简单了.

时间复杂度: O(N!)
空间复杂度: O(N^2)

具体见https://leetcode.com/problems/n-queens/solution/