问题描述
N皇后问题是指在N*N的棋盘上要摆N个皇后,
要求:任何两个皇后不同行,不同列也不再同一条斜线上,
求给一个整数N,返回N皇后的摆法数。
示例
示例1
输入
8
输出
92
解决思路
思路
- 回溯法:要保证n个皇后不同行,不同列,不同斜线,只需要满足下面3个条件即可
(1)N个皇后不同行,通过s1存储该行上的皇后
(2)N个皇后不同左上角如图斜线方向,通过s2存储该方向的皇后。我们会发现位于统一斜线上的坐标满足,x坐标和y坐标的和相等。例如:(1,0) (0,1)在同一斜线上,和均为1
(3)N个皇后不同右下角如图斜线方向,通过s3存储该方向的皇后。我们会发现位于统一斜线上的坐标满足,x坐标和y坐标的差相等。例如:(5,0) (6,1)在同一斜线上,差均为5
代码实现
// 思路1
public class Solution {
private int count;
/**
* @param n int整型 the n
* @return int整型
*/
public int Nqueen (int n) {
// write code here
count = 0;
Set<Integer> s1 = new HashSet<>(), s2 = new HashSet<>(), s3 = new HashSet<>();
Nqueen(n, 0, s1, s2, s3);
return count;
}
public void Nqueen (int n, int row, Set<Integer> s1, Set<Integer> s2, Set<Integer> s3) {
if (row == n) {
count++;
return;
} else {
for (int i = 0; i < n; i++) {
// 判断是否同行
if (s1.contains(i)) {
continue;
}
// 判断左上角方向
int d1 = row + i;
if (s2.contains(d1)) {
continue;
}
// 判断左下角方向
int d2 = row - i;
if (s3.contains(d2)) {
continue;
}
s1.add(i);
s2.add(d1);
s3.add(d2);
Nqueen(n, row + 1, s1, s2, s3);
s1.remove(i);
s2.remove(d1);
s3.remove(d2);
}
}
}
}
时间复杂度分析:
O(N!):其中 N 是皇后数量。
空间复杂度分析:
O(N):其中 N 是皇后数量。空间复杂度主要取决于递归调用层数、记录每行放置的皇后的列下标的数组以及三个集合,递归调用层数不会超过 N,每个集合的元素个数都不会超过 N。
小伙伴如果想测试的话,可以直接到牛客网这个链接做测试
N皇后问题-牛客网(ps:文件的解法会超时,效果版可以参考题解,这里说的主要是方法)