55utah / leetcode

leetcode解题记录和总结

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

51. N皇后问题 【回溯法】

55utah opened this issue · comments

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('')
        })
    })
};