列表

详情


面试题 08.12. 八皇后

设计一种算法,打印 N 皇后在 N × N 棋盘上的各种摆法,其中每个皇后都不同行、不同列,也不在对角线上。这里的“对角线”指的是所有的对角线,不只是平分整个棋盘的那两条对角线。

注意:本题相对原题做了扩展

示例:

 输入:4
 输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
 解释: 4 皇后问题存在如下两个不同的解法。
[
 [".Q..",  // 解法 1
  "...Q",
  "Q...",
  "..Q."],

 ["..Q.",  // 解法 2
  "Q...",
  "...Q",
  ".Q.."]
]

原站题解

去查看

上次编辑到这里,代码来自缓存 点击恢复默认模板
class Solution { public: vector<vector<string>> solveNQueens(int n) { } };

javascript 解法, 执行用时: 84 ms, 内存消耗: 46 MB, 提交时间: 2023-03-21 10:16:03

/**
 * @param {number} n
 * @return {string[][]}
 */
var solveNQueens = function(n) {
    //存放列,对角线是否已经放置皇后的数组;
    let cols=[],diag1=[],diag2=[];
    //棋盘数组;
    let mat=new Array(n).fill("").map(()=>new Array(n).fill("."));
    //结果数组,可能有多种方案;
    let res=[];
    //回溯函数,如果方案可行,会运行到最后一行(row==n);
    let back_tracking=function(row=0){
        if(row==n){
            //如果结果可行,复制一份;
            let ans=mat.slice();
            ans=ans.map(it=>it.join(""));
            res.push(ans);
            return;
        }
        for(let col=0;col<n;col++){
            //判断当前位置是否可以放置皇后;
            if(cols.includes(col)||diag1.includes(row-col)||diag2.includes(row+col)) continue;
            mat[row][col]="Q";
            cols.push(col);
            diag1.push(row-col);
            diag2.push(row+col);
            //执行回溯;
            back_tracking(row+1);
            //执行回溯后恢复现场;
            mat[row][col]=".";
            cols.pop();
            diag1.pop();
            diag2.pop();
        }
    }
    back_tracking();
    return res;
};

golang 解法, 执行用时: 8 ms, 内存消耗: 3.2 MB, 提交时间: 2023-03-21 10:15:42

func solveNQueens(n int) [][]string {
    cols:=map[int]bool{}
    l2r:=map[int]bool{}
    r2l:=map[int]bool{}
    ans:=[][]string{}
    matrix:=[][]byte{}
    for i:=0;i<n;i++{
        tmp:=make([]byte,n)
        for j:=0;j<n;j++{
            tmp[j]='.'
        }
        matrix=append(matrix,tmp)
    }
    var back_tracking func(int)
    back_tracking=func(i int){
        if i==n{
            tmp:=[]string{}
            for _,row:=range matrix{
                tmp=append(tmp,string(row))
            }
            ans=append(ans,tmp)
            return
        }
        for j:=0;j<n;j++{
            if _,ok:=cols[j];ok{
                continue
            }
            if _,ok:=l2r[i-j];ok{
                continue
            }
            if _,ok:=r2l[i+j];ok{
                continue
            }
            matrix[i][j]='Q'
            cols[j]=true
            l2r[i-j]=true
            r2l[i+j]=true
            back_tracking(i+1)
            matrix[i][j]='.'
            delete(cols,j)
            delete(l2r,i-j)
            delete(r2l,i+j)
        }
    }
    back_tracking(0)
    return ans
}

python3 解法, 执行用时: 80 ms, 内存消耗: 15.2 MB, 提交时间: 2023-03-21 10:14:22

class Solution(object):
    def solveNQueens(self, n):
        # 生成N*N的棋盘,填充棋盘,每个格子默认是“。”表示没有放置皇后
        arr = [["." for _ in range(n)] for _ in range(n)]
        res = []
        # 检查当前的行和列是否可以放置皇后
        def check(x,y):
            # 检查竖着的一列是否有皇后
            for i in range(x):
                if arr[i][y]=="Q":
                    return False
            # 检查左上到右下的斜边是否有皇后        
            i,j = x-1,y-1
            while i>=0 and j>=0:
                if arr[i][j]=="Q":
                    return False
                i,j = i-1,j-1
            # 检查左下到右上的斜边是否有皇后    
            i,j = x-1,y+1
            while i>=0 and j<n:
                if arr[i][j]=="Q":
                    return False
                i,j = i-1,j+1
            return True
        def dfs(x):
            # x是从0开始计算的
            # 当x==n时所有行的皇后都放置完毕,此时记录结果
            if x==n:
                res.append( ["".join(arr[i]) for i in range(n)] )
                return 
            # 遍历每一列    
            for y in range(n):
                # 检查[x,y]这一坐标是否可以放置皇后
                # 如果满足条件,就放置皇后,并继续检查下一行
                if check(x,y):
                    arr[x][y] = "Q"
                    dfs(x+1)
                    arr[x][y] = "."
        dfs(0)
        return res

java 解法, 执行用时: 2 ms, 内存消耗: 41.8 MB, 提交时间: 2023-03-21 10:12:40

class Solution {
    private char[][] array; // 棋盘,放置所有皇后
    private int[] rowIndex; // 每个皇后的列坐标,主要用于位置校验。

    private List<List<String>> res = new ArrayList<>();


    public List<List<String>> solveNQueens(int n) {
        array = new char[n][n];
        rowIndex = new int[n];
        check(n, 0);
        return res;
    }

    // 摆放
    // n:皇后位数
    // index:当前皇后
    private void check(int n, int index) {
        if (index == n) {
            List<String> list = new ArrayList<>();
            for (char[] c : array) {
                list.add(new String(c));
            }
            res.add(list);
            return;
        }
        Arrays.fill(array[index], '.');
        for (int i = 0; i < n; i++) {
            rowIndex[index] = i; // 当前皇后所在棋盘中的列坐标
            array[index][i] = 'Q'; // 放置当前皇后在index行,i列
            if (!judge(index)) {
                array[index][i] = '.'; // 校验不通过
                continue;
            }
            check(n, index + 1); // 递归进行下一位皇后的放置
            array[index][i] = '.';
        }
    }

    // 校验皇后们的位置是否合法:
    // 每个新来的皇后都与之前的皇后进行校验
    // index:1,代表第二个皇后, 她将与(第一个)皇后进行位置校验,检验通过说明当前皇后们摆放是合法的。
    // index:2,代表第三个皇后,此时前两位皇后的位置已经校验完成,她将与前面(第一个、第二个)皇后进行位置校验。
    private boolean judge(int index) {
        int n = array.length;
        for (int i = 0; i < index; i++) {
            if (rowIndex[i] == rowIndex[index] 
                    || Math.abs(rowIndex[index] - rowIndex[i]) == Math.abs(index - i)) {
                return false;
            }
        }
        return true;
    }
}

python3 解法, 执行用时: 36 ms, 内存消耗: 15.4 MB, 提交时间: 2023-03-21 10:12:27

class Solution:
    def solveNQueens(self, n: int) -> List[List[str]]:
        def generateBoard():
            board = list()
            for i in range(n):
                row[queens[i]] = "Q"
                board.append("".join(row))
                row[queens[i]] = "."
            return board

        def solve(row: int, columns: int, diagonals1: int, diagonals2: int):
            if row == n:
                board = generateBoard()
                solutions.append(board)
            else:
                availablePositions = ((1 << n) - 1) & (~(columns | diagonals1 | diagonals2))
                while availablePositions:
                    position = availablePositions & (-availablePositions)
                    availablePositions = availablePositions & (availablePositions - 1)
                    column = bin(position - 1).count("1")
                    queens[row] = column
                    solve(row + 1, columns | position, (diagonals1 | position) << 1, (diagonals2 | position) >> 1)

        solutions = list()
        queens = [-1] * n
        row = ["."] * n
        solve(0, 0, 0, 0)
        return solutions

python3 解法, 执行用时: 40 ms, 内存消耗: 15.5 MB, 提交时间: 2023-03-21 10:12:03

class Solution:
    def solveNQueens(self, n: int) -> List[List[str]]:
        def generateBoard():
            board = list()
            for i in range(n):
                row[queens[i]] = "Q"
                board.append("".join(row))
                row[queens[i]] = "."
            return board

        def backtrack(row: int):
            if row == n:
                board = generateBoard()
                solutions.append(board)
            else:
                for i in range(n):
                    if i in columns or row - i in diagonal1 or row + i in diagonal2:
                        continue
                    queens[row] = i
                    columns.add(i)
                    diagonal1.add(row - i)
                    diagonal2.add(row + i)
                    backtrack(row + 1)
                    columns.remove(i)
                    diagonal1.remove(row - i)
                    diagonal2.remove(row + i)
                    
        solutions = list()
        queens = [-1] * n
        columns = set()
        diagonal1 = set()
        diagonal2 = set()
        row = ["."] * n
        backtrack(0)
        return solutions

上一题