LeetCode51. N-Queens N皇后问题

The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other.

LeetCode51. N-Queens N皇后问题_第1张图片
八皇后

Given an integer n, return all distinct solutions to the n-queens puzzle.

Each solution contains a distinct board configuration of the n-queens' placement, where 'Q' and '.' both indicate a queen and an empty space respectively.

N皇后问题是一个经典的算法问题,求N×N的国际象棋棋盘上能摆放多少个皇后,且她们之间不相互攻击,要输出所有可能的摆法。皇后的攻击范围是同一行、同一列以及同在两条45°斜线上的棋子。

解本题的关键是选择一个合适的数据结构来记录放皇后的位置,还要方便检验各个位置是否冲突。使用x和y坐标来记录位置是最直接的,然而保存两个数要用额外的数据结构才行(特殊情况可以用一个int打包),记录下来后判断位置是否冲突也比较麻烦。

经过思考,使用一个int[N]数组来保存皇后的位置是最合适的。数组下标代表y坐标,数组中的数0~N-1代表x坐标。这样保证y坐标不会重复(不会在同一行),判断x坐标是否重复只要遍历数组看是否有重复数字,判断是否在同一斜线也很方便:假设当前位置是int[yi]=xi,从当前位置向前移动,判断 (int[yi-1]==xi+1 || int[yi-1]==xi-1), (int[yi-12]==xi+2 || int[yi-2]==xi-2)...即可。

解决了数据结构和位置检查的问题,剩下的算法就很简单:从位置0开始,检查当前位置能放0~N-1中的哪个数,如果能放且是最后一个数,就把数组转换一下输出,如果没到最后一个数,就对下一个位置递归计算。

代码如下,本算法击败了98%的java算法。

    public static List> solveNQueens(int n) {
        List> res = new ArrayList<>();
        int[] a = new int[n];
        solveNQueens(res, a, 0);
        return res;
    }

    public static void solveNQueens(List> res, int[] a, int pos) {
        int n = a.length;
        for(int j = 0; j < n; j++) {
            if(check(a, pos, j)) {
                a[pos] = j;
                if(pos == n - 1) { // save
                    char[][] board = new char[n][n];
                    for(char[] b : board) {
                        Arrays.fill(b, '.');
                    }
                    List list = new ArrayList<>();
                    for(int i = 0; i < n; i++) {
                        board[i][a[i]] = 'Q';
                        list.add(new String(board[i]));
                    }
                    res.add(list);
                } else solveNQueens(res, a, pos + 1);
            }
        }
    }

    public static boolean check(int[] a, int pos, int j) {
        for(int k = pos - 1; k >= 0; k--) {
            if(a[k] == j) return false;
        }
        for(int k = pos - 1; k >= 0; k--) {
            int diff = pos - k;
            if(a[k] == j + diff || a[k] == j - diff) return false;
        }
        return true;
    }

你可能感兴趣的:(LeetCode51. N-Queens N皇后问题)