「刷刷刷」51.N皇后

题目

难度:困难

n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。

每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。

提示:

  • 1 <= n <= 9
  • 皇后彼此不能相互攻击,也就是说:任何两个皇后都不能处于同一条横行、纵行或斜线上。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/n-queens

思路

还是回溯算法,同 37. 解数独

需要判断每个位置能否放一个皇后下去,每行每列只能有一个皇后,比较容易判断,关键在于斜着的一撇一捺。

把棋盘放在坐标系看,将撇和捺看作两条斜率为 1 的直线,也就是 y = kx + c(k = 1或-1)(小学知识?)
也就是: y + x = c 和 y - x = c

那么判断一个位置的斜向有没有其它皇后就很简单了:
只需要两个集合,分别把 y + x 和 y - x 放进去就好了,后边的位置判断集合中是否存在。

按行遍历,每行只能放一个皇后,再需要一个集合记录已使用的列,就可以了。

代码

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
class Solution {

Set<Integer> col = new HashSet<>();
Set<Integer> pie = new HashSet<>();
Set<Integer> na = new HashSet<>();

public List<List<String>> solveNQueens(int n) {

List<List<String>> resList = new ArrayList<>();
int[] queens = new int[n];
Arrays.fill(queens, -1);

solve(n, 0, queens, resList);

return resList;
}


private void solve(int n, int row, int[] queens, List<List<String>> resList) {

if (row == n) {
List<String> res = generate(queens, n);
resList.add(res);
}

for (int i = 0; i < n; i++) {

if (!col.contains(i) && !pie.contains(i + row) && !na.contains(i - row)) {

queens[row] = i;
col.add(i);
pie.add(i + row);
na.add(i - row);

solve(n, row + 1, queens, resList);

// 回溯
queens[row] = -1;
col.remove(i);
pie.remove(i + row);
na.remove(i - row);

}
}
}

public List<String> generate(int[] queens, int n) {
List<String> res = new ArrayList<String>();
for (int i = 0; i < n; i++) {
char[] row = new char[n];
Arrays.fill(row, '.');
row[queens[i]] = 'Q';
res.add(new String(row));
}
return res;
}
}

作者:prik
永久链接: https://trzoey.github.io/blog-prik/algorithmic/51.n-queens/
转载请注明出处,谢谢合作💓。