持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第8天,点击查看活动详情
按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。
示例
输入: n = 4
输出:
[
[
".Q..",
"...Q",
"Q...",
"..Q."
],
[
"..Q.",
"Q...",
"...Q",
".Q.."
]
]
思路
根据示例来寻找一些规律
- 先看输出中的第一个数组,锁定第一条数据中的
Q的索引位置是0, 1- 在
0, 1时,右侧斜线(同一斜线可攻击,故而不能放置其他的Q)位置是:1,2和2,3 - 可以发现行 - 列 是一样的
- 在
- 第二个数组,第一条数据中
Q的索引是0, 2- 左边斜线的位置是:
1,1和0,2 - 发现 行 + 列 是一样的
- 左边斜线的位置是:
所以我们目前发现的限制条件是
- 行不能一样
- 列不能一样
- 行 - 列 不能一样
- 行 + 列 不能一样
代码实现
var solveNQueens = function(n) {
let ret = [] // 结果存放数组
find(0) // 从第1行(索引为0)开始查找
return ret;
// tmp的作用:记录之前的路径
// tmp的索引是行数据:tmp是一个数组,数组中每个元素的值都记录的是列索引,数组本身位置的索引记录的是行索引
// 例如:tmp = [1, 3, 0, 2] 代表 "0,1"、"1,3"、"2,0"、"3,2" 这四个地方存放的 Q
// row 代表当前行
function find(row, tmp = []) {
if(row === n) {
// 找完了 n-1 就已经是最后一行了(一共n行),tmp就是本次的摆放位置
ret.push(tmp.map(c => {
let arr = new Array(n).fill(".")
arr[c] = "Q"
return arr.join("")
}))
}
// 逐列查找,在当前行中依次遍历每一个元素(这里已经排除了行相等的情况了)
for(let col=0; col<n; col++) {
// 是否不能放置
let cantSet = tmp.some((ci, ri) => {
// ci和ri是之前摆放棋子的行列索引
// col和row是当前所在位置的索引
return ci === col // 列相同(此列已经存放过其它Q了)
|| (ri-ci) === (row-col) // 行-列相同(右侧斜线已经有其他Q了)
|| (ri+ci)===(row+col) // 行+列相同(左侧斜线已经有其他Q了)
})
if(cantSet) continue // 本行的当前列不能放,继续本行的下一列
// 如果能放置,则将列放进 tmp 中,继续下一行
find(row+1, [...tmp, col])
}
}
}