2022-09-11 【我的刷题日记】LeetCode 51 N皇后

思路:本题主要分为几个部分来思考,如何通过n来创建棋盘,如何判断回溯的终止条件,如何把最后的方案棋盘转化为List集合,如何判断当前放置的皇后是否合法。
我们知道回溯函数包含for来进行横向的遍历,所以我们只需要增加一个值row来控制不同的行数即可,在单行内使用for来进行横向的遍历,确定是否可以在当前row放置皇后。而当row的值等于最后一行的时候,说明已经成功在最后一行放置了皇后,所以回溯函数就可以套用之前的终止条件加上for循环的模板

 public void backTracking(char[][] chessBoard ,int n,int row){
//        当row = n说明最后一行也已经放了一个Q 已经找到了一种方案
        if(row == n){
//            输出整个棋盘
            res.add(inputList(chessBoard));
            return;
        }
//        每次都在一行中选择位置放Q
        for (int col = 0;col < n;col++){
//            只有在当前位置合法的时候才会放Q
            if (isVaild(chessBoard,row,col,n)){
                chessBoard[row][col] = 'Q';
                backTracking(chessBoard, n, row+1);
                chessBoard[row][col] = '.';
            }
        }
    }

判断当前皇后是否合法:按照题意,皇后当前行列斜线均不可有其他皇后,所以我们要针对这三项分别判断,斜线也要分为45°斜线和135°斜线分别判断,注意这里我们只需要判断当前放置位置之前的行和斜线不存在皇后即可,之后还未遍历到的行不用进行判断,只要保证之前的一直合法,那么整体也会合法。同时,我们没必要进行对于行的合法判断,因为回溯函数中使用for进行横向遍历,已经保证了一行最多只会有一个Q.

//    判断当前皇后是否合法
    public boolean isVaild(char[][] chessBoard,int row,int col,int n){
//        判断当前列有无Q
        for (int i = 0;i < row; i++){
            if (chessBoard[i][col] == 'Q') return false;
        }
////        没有必要判断行,因为同一行每次只会放一个Q
//        for (int i = 0;i < col; i++){
//            if (chessBoard[row][i] == 'Q') return false;
//        }
//        判断45°斜线是否有Q
//        剪枝,只需要判断已经走过的行即可,还没走的行没有判断的必要
        for (int i = row - 1, j = col - 1 ; i >=0 && j >= 0;i--,j--){
            if (chessBoard[i][j] == 'Q') return false;
        }
//        判断135°斜线是否有Q
        for (int i = row - 1,j = col + 1;i >=0&&j <= n - 1;i--,j++){
            if (chessBoard[i][j] == 'Q') return false;
        }
        return true;
    }

整体代码

class Solution {
    public List> res = new ArrayList<>();
    public List> solveNQueens(int n) {
//        根据提供的n构造棋盘
        char[][] chessBoard = new char[n][n];
//        棋盘默认为.
        for (char[] c : chessBoard){
            Arrays.fill(c,'.');
        }
        backTracking(chessBoard,n,0);
        return res;
    }
    public void backTracking(char[][] chessBoard ,int n,int row){
//        当row = n说明最后一行也已经放了一个Q 已经找到了一种方案
        if(row == n){
//            输出整个棋盘
            res.add(inputList(chessBoard));
            return;
        }
//        每次都在一行中选择位置放Q
        for (int col = 0;col < n;col++){
//            只有在当前位置合法的时候才会放Q
            if (isVaild(chessBoard,row,col,n)){
                chessBoard[row][col] = 'Q';
                backTracking(chessBoard, n, row+1);
                chessBoard[row][col] = '.';
            }
        }
    }
//    输出当前棋盘 二维char转为list需要写一个函数来转换
    public List inputList(char[][] chessBoard){
        List list = new LinkedList<>();
        for(char[] chars : chessBoard){
            list.add(String.copyValueOf(chars));
        }
        return list;
    }
//    判断当前皇后是否合法
    public boolean isVaild(char[][] chessBoard,int row,int col,int n){
//        判断当前列有无Q
        for (int i = 0;i < row; i++){
            if (chessBoard[i][col] == 'Q') return false;
        }
////        没有必要判断行,因为同一行每次只会放一个Q
//        for (int i = 0;i < col; i++){
//            if (chessBoard[row][i] == 'Q') return false;
//        }
//        判断45°斜线是否有Q
//        剪枝,只需要判断已经走过的行即可,还没走的行没有判断的必要
        for (int i = row - 1, j = col - 1 ; i >=0 && j >= 0;i--,j--){
            if (chessBoard[i][j] == 'Q') return false;
        }
//        判断135°斜线是否有Q
        for (int i = row - 1,j = col + 1;i >=0&&j <= n - 1;i--,j++){
            if (chessBoard[i][j] == 'Q') return false;
        }
        return true;
    }
}

你可能感兴趣的:(2022-09-11 【我的刷题日记】LeetCode 51 N皇后)