【JS每日一算法】46. N 皇后II(递归回溯、查询法)

187 阅读3分钟

n皇后问题研究的是如何将n个皇后放置在n × n的棋盘上,并且使皇后彼此之间不能相互攻击。

给你一个整数n,返回n皇后问题不同的解决方案的数量。

提示:

  • 1 <= n <= 9

 示例:

queens.jpg

输入: n = 4
输出: 2
解释: 如上图所示,4 皇后问题存在两个不同的解法

代码:

/**
 * @description: 递归回溯    TC:O(2^n)  SC:O(n)
 * @author: JunLiangWang
 * @param {*} n   给定矩阵大小
 * @return {*}
 */
function recursionBacktracking(n) {
    
    /**
     * 该方案与N皇后1问题一样,利用递归回溯的方式,通过递归逐行遍历矩阵元素,然后在
     * 递归中逐列遍历当前行的元素,找到与已找到的点(points)不同行/不同列/不同对角线
     * 的点,并将该点加入到已找到的点(points)中,从下一行继续递归,直到递归完矩阵所
     * 有行,证明已找到所有符合条件的点。
     * 
     * 判断当前点是否与已找到的点
     * 不同行(由于是逐行递归的,因此当前行的点肯定与已找到的点不同行,此处无需判断)
     * 不同列(即:已找到的点的列不等于当前点的列)
     * 不同对角线(即:已找到的点的列与行之和/差不等于当前点的列与行之和/差)
     */

    // 定义记录解决方案数量变量
    let count = 0;

    /**
     * @description: 递归回溯
     * @author: JunLiangWang
     * @param {*} row      当前行
     * @param {*} points   已选中的点
     * @return {*}
     */    
    function recursion(row, points) {
        
        // 如果当前行超出了矩阵大小,证明已找到所有符合条件的点
        if (row === n) {
            // 解决方案+1
            count++;
            return;
        }

        // 如果当前行(currentRow)未超出矩阵大小,则逐列遍历当前行的元素,找到与
        // 已找到的点(points)不同行/不同列/不同对角线的点,并将该点加入到已找到
        // 的点(points)中,从下一行继续递归
        
        // 逐列遍历当前行(currentRow)的元素
        for (let col = 0; col < n; col++) {

            // 遍历已找到的点,判断当前点是否与已找到的点
            // 不同行(由于是逐行递归的,因此当前行的点肯定与已找到的点不同行,此处无需判断)
            // 不同列(即:已找到的点的列不等于当前点的列)
            // 不同对角线(即:已找到的点的列与行之和/差不等于当前点的列与行之和/差)
            let index = 0;
            while (index < points.length && points[index].col !== col &&
                points[index].col + points[index].row !== col + row &&
                points[index].col - points[index].row !== col - row) index++;
                
            // 如果index不等于points数组长度,证明已找到的点中有与当前点同行/同列/同对
            // 角线的情况,否则,则没有该情况,将该点加入到已找到的点(points)中,从下一
            // 行继续递归
            if (index === points.length) {
                //将该点加入到已找到的点(points)中,从下一行继续递归
                recursion(row + 1, [...points, {
                    row: row,
                    col: col
                }])
            }
        }
    }

    // 调用递归
    recursion(0,[]);
    // 返回结果
    return count;
}


/**
 * @description: 查询法    TC:O(1)  SC:O(1)
 * @author: JunLiangWang
 * @param {*} n   给定矩阵大小
 * @return {*}
 */
function queryMethod(n){
    /**
     * 由于n的范围为1-9,数量并不大,因此我们可以记录1到9
     * 所有值,然后返回查询结果即可
     */
    return [1,0,0,2,10,4,40,92,352][n-1]
}

来源:力扣(LeetCode)