数据结构与算法之递归: LeetCode 51. N 皇后 (Ts版)

N 皇后

  • https://leetcode.cn/problems/permutations-ii/description/

描述

  • 按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子
  • n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击
  • 给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案
  • 每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位

示例 1

数据结构与算法之递归: LeetCode 51. N 皇后 (Ts版)_第1张图片
输入:n = 4
输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]

解释:如上图所示,4 皇后问题存在两个不同的解法。

示例 2

输入:n = 1
输出:[["Q"]]

提示

  • 1 <= n <= 9

Typescript 版算法实现


1 ) 方案1: 基于集合的回溯

function solveNQueens(n: number): string[][] {
    const solutions = [];
    const queens = new Array(n).fill(-1);
    const columns = new Set();
    const diagonal1 = new Set();
    const diagonal2 = new Set();
    const row = new Array(n).fill(".");

    function generateBoard() {
        const board = [];
        for (let i = 0; i < n; i++) {
            row[queens[i]] = "Q";
            board.push(row.join(""));
            row[queens[i]] = ".";
        }
        return board;
    }

    function backtrack(row) {
        if (row === n) {
            const board = generateBoard();
            solutions.push(board);
        } else {
            for (let i = 0; i < n; i++) {
                if (columns.has(i) || diagonal1.has(row - i) || diagonal2.has(row + i)) {
                    continue;
                }
                queens[row] = i;
                columns.add(i);
                diagonal1.add(row - i);
                diagonal2.add(row + i);
                backtrack(row + 1);
                columns.delete(i);
                diagonal1.delete(row - i);
                diagonal2.delete(row + i);
            }
        }
    }

    backtrack(0);
    return solutions;
};

2 ) 方案2: 基于位运算的回溯

function solveNQueens(n: number): string[][] {
    const solutions = [];
    const queens = new Array(n).fill(-1);
    const row = new Array(n).fill(".");

    function generateBoard() {
        const board = [];
        for (let i = 0; i < n; i++) {
            row[queens[i]] = "Q";
            board.push(row.join(""));
            row[queens[i]] = ".";
        }
        return board;
    }

    function solve(row, columns, diagonals1, diagonals2) {
        if (row === n) {
            const board = generateBoard();
            solutions.push(board);
        } else {
            let availablePositions = ((1 << n) - 1) & (~(columns | diagonals1 | diagonals2));
            while (availablePositions) {
                const position = availablePositions & -availablePositions;
                availablePositions &= availablePositions - 1;
                const column = Math.log2(position);
                queens[row] = column;
                solve(row + 1, columns | position, (diagonals1 | position) << 1, (diagonals2 | position) >> 1);
            }
        }
    }

    solve(0, 0, 0, 0);
    return solutions;
};

3 ) 方案3:回溯-一般思路

function solveNQueens(n: number): string[][] {
    // [1,3,0,2]
    const ret = []
    const path = []

    function backtrack(row, tmp) {
        if (row === n) {
            ret.push(
                tmp.map(c => {
                    let arr = new Array(n).fill('.')
                    arr[c] = 'Q'
                    return arr.join('')
                })
            )
        }
        // row 第几行
        for (let col = 0; col < n; col++) {
            let canNotSet = tmp.some((c, r) => {
                return c == col || ((r - c) === (row - col)) || ((r + c) === (row + col))
            })
            if (canNotSet) {
                continue
            }
            backtrack(row + 1, [...tmp, col])

        }
    }
    // r c    row col 
    // r==row c==col r-c==row-col r+c row+col

    backtrack(0, path)
    return ret
};

你可能感兴趣的:(Data,Structure,and,Algorithms,leetcode,算法)