Leetcode--Java--51. N 皇后

题目描述

n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。

每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。

样例描述

在这里插入图片描述

思路

回溯 + 剪枝

  1. 按行来放置皇后,每行只能放一个。
  2. 检查当前位置是否可以放。具体检查所在的列,左上的对角线和右上的对角线。不需要检查行,因为每行只有一个。不需要检查左下和右下,这里剪枝了。因为每次放时保证与之前已经放过的不重复,而行是从上往下来的,所以不需要检查左下和右下。
  3. 检查对角线能否放置时,设置一个增幅变量,每次检查当前位置开始的对角线上的所有元素(保证不出界的情况下)是否存在皇后。只要有一个就返回false
  4. String.valueOf()能将字符数组转成字符串。

代码

class Solution {
    List<List<String>> res = new ArrayList<>();
    public List<List<String>> solveNQueens(int n) {
        //初始化棋盘
        char board[][] = new char[n][n];
        for (char[] ch: board) {
            Arrays.fill(ch, '.');
        }
        backTrack(board, 0, n);
        return res;
    }
    public void backTrack(char board[][], int row, int n) {
        //按行来放皇后,若等于n说明找到一个棋盘满足
        if (row == n) {
           List<String> list = new ArrayList<>();
           for (int i = 0; i < n; i ++ ) {
               //字符数组转化为字符串,一行一行转入到棋盘中
              list.add(String.valueOf(board[i]));
           }
         //棋盘加入结果集
         res.add(list);
         return;
        }
        //对于这行的每个位置
        for (int j = 0; j < n; j ++ ) {
           //如果可以放置,才进行放置和继续下一个
            if (check(board, row, j, n)) {
                 board[row][j] = 'Q';
                 backTrack(board, row + 1, n);
                 //恢复现场
                 board[row][j] = '.';
            }
        }
    }
    public boolean check(char board[][], int i, int j, int n ) {
        //由于是一行只放一个皇后,所以不需要检查行。 下面检查出现Q就返回false
        //检查所在的列
        for (int k = 0; k < n; k ++ ) {
            if (board[k][j] == 'Q') return false;
        }
        //下面k都是控制增减的幅度从1开始递增到n
        //检查左上方的对角线
        for (int k = 1; k < n; k ++ ) {
            if (i - k >= 0 && j - k >= 0 && board[i - k][j - k] == 'Q') return false;
        }
        //检查右上方的对角线
        for (int k = 1; k < n; k ++ ) {
            if (i - k >= 0 && j + k < n && board[i - k][j + k] == 'Q') return false;
        }
        return true;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值