题目
N皇后问题是指在N*N的棋盘.上要摆N个皇后,要求任何两个皇后不同行、不同列,也不在同一条斜线上。 给定一个整数n,返回N皇后的摆法有多少种。n=1,返回1。n=2或3,2皇后和3皇后问题无论怎么摆都不行,返回0。n=8,返回92。
- n*n的棋盘,要放n个皇后,注意皇后的个数是要和棋盘行数相同的
- n*n的棋盘要放n个皇后,并且还必须不同列不同行不同对角线,所以每个皇后必须分散在每一行(列)才有可能
- 要遍历出每一种结果,即从第一行第一列开始放一个皇后,然后采取按行深度遍历,从第二行放置符合条件的皇后,同理从第三行、第四行找符合条件的皇后,为了减少遍历次数(动态规划),只有当前行符合才继续去下一行找(需要记录符合的历史节点),第一行第一列遍历结束后,接着从第一行第二列重复这样的过程,最终第一行最后一列遍历结束时,就能统计出所有结果
function NQueen(n) {
let line = 0, //当前遍历到的行数
records = [], // 已经记录到的可以摆放的皇后位置,a[0]=2,表示第一行第三列
res = 0;
if (n < 1) {
return 0;
}
function getN(line, n, records) {
if (line === n) {
//当已经遍历完所有的行,
res++;
}
for (let j = 0; j < n; j++) {
// 只会和在当前行之前的行所记录的点判断,且是从上到下的深度遍历,上次对应行记录的数会被当前满足的点覆盖掉
// 比如假设上次记录的是a[0]=b0,a[1]=b1,a[2]=b2,a[3]=b3
// 在重新开始从第一行记录时,因为只比较前面的行,所以a[0]会被重写,同理a[1]某个点满足时也会重写a[1]
// 所以之前records记录不用清除
if (isValid(line, j, records)) {
records[line] = j;
getN(line + 1, n, records);
}
}
}
// 判断和之前的皇后不同列、不同对角线
function isValid(line, j, records) {
for (let i = 0; i < line; i++) {
if (records[i] == j || Math.abs(records[i] - j) == Math.abs(i - line)) {
return false;
}
}
return true;
}
getN(line, n, records);
return res;
}
console.log(NQueen(4));