51. N皇后问题 【回溯法】
55utah opened this issue · comments
阿星 commented
n 皇后问题
研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。
示例 1:
输入:n = 4
输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
解释:如上图所示,4 皇后问题存在两个不同的解法。
示例 2:
输入:n = 1
输出:[["Q"]]
提示:
1 <= n <= 9
皇后彼此不能相互攻击,也就是说:任何两个皇后都不能处于同一条横行、纵行或斜线上。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/n-queens
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
// Typescript版本的回溯法
function solveNQueens(n: number): string[][] {
if (n == 1) return [['Q']]
// n个皇后放在n*n的网格内,必定是一行一个,使用一维数组处理
// 避免通常思维的二维数组,存在复杂度高、引用类型等问题
// 利用特性降低计算难度,降为一维数组(默认满足了每个皇后左右直线不能有皇后的条件)
const result = []
// 使用回溯法思路,从上到下按行遍历,每一行判断棋子可放在哪个位置,然后迭代
const go = (rows: number[], count: number) => {
// 已经是n个棋子返回
if (count >= n) {
result.push(rows)
return true
}
// 遍历当前行每个位置
for (let i = 0; i < n; i++) {
// 斜对角直线上所有位置都不能有棋子
// 判断 (count, i) 与 (k, j) 元素判断是否对角线 + 本列是否有棋子
// 满足上下和对角线不能有棋子要求
const invalid = rows.some((j, k) => Math.abs(count - k) === Math.abs(i - j) || j === i)
if (!invalid) {
// 进入下一层迭代
go(rows.concat(i), count + 1)
}
}
}
// 初始化数据执行
go([], 0)
// 最后再组装输出
return result.map((row) => {
return row.map(p => {
const arr = new Array(n).fill('.')
arr[p] = 'Q'
return arr.join('')
})
})
};