代码随想录算法训练营第30天| 51. N皇后、回溯总结

51. N皇后

完成

思路:

如何用回溯法搜索二维棋盘是这道题目和之前不一样的地方,也是题目的难点。
在树形结构中,同层取同一行棋盘的不同列遍历。每递归一次就往下遍历一行。
在这里插入图片描述

代码

class Solution {
    List<List<String>> res = new ArrayList<>();
    // 棋盘
    char[][] chessboard;
    public List<List<String>> solveNQueens(int n) {
        chessboard = new char[n][n];
        // 初始化棋盘
        for (char[] c : chessboard) {
            Arrays.fill(c, '.');
        }
        backTrack(n, 0);
        return res;
    }


    public void backTrack(int n, int row) {
        if (row == n) {
            // 把合法的棋盘情况添加进去
            res.add(Array2List(chessboard));
            return;
        }
        // 同层遍历列
        for (int col = 0;col < n; ++col) {
            // 判断是否存在同行同列同斜线的棋子
            if (isValid (row, col, n, chessboard)) {
                chessboard[row][col] = 'Q';
                backTrack(n, row+1);
                chessboard[row][col] = '.';
            }
        }

    }


    public List Array2List(char[][] chessboard) {
        List<String> list = new ArrayList<>();

        for (char[] c : chessboard) {
            list.add(String.copyValueOf(c));
        }
        return list;
    }


    public boolean isValid(int row, int col, int n, char[][] chessboard) {
        // 检查列
        for (int i=0; i<row; ++i) { // 相当于剪枝
            if (chessboard[i][col] == 'Q') {
                return false;
            }
        }

        // 检查45度对角线
        for (int i=row-1, j=col-1; i>=0 && j>=0; i--, j--) {
            if (chessboard[i][j] == 'Q') {
                return false;
            }
        }

        // 检查135度对角线
        for (int i=row-1, j=col+1; i>=0 && j<=n-1; i--, j++) {
            if (chessboard[i][j] == 'Q') {
                return false;
            }
        }
        return true;
    }
}

总结

回溯法就是暴力搜索,并不是什么高效的算法,最多再剪枝一下。

回溯算法能解决如下问题:

  • 组合问题:N个数里面按一定规则找出k个数的集合
  • 切割问题:一个字符串按一定规则有几种切割方式请添加图片描述
  • 排列问题:N个数按一定规则全排列,有几种排列方式
  • 子集问题:一个N个数的集合里有多少符合条件的子集
  • 棋盘问题:N皇后,解数独等等
  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值