Leetcode51-N皇后详细题解简单易懂

题目描述

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

8皇后的一种解法
上图为 8 皇后问题的一种解法。

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

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

示例:

输入: 4
输出: [
 [".Q..",  // 解法 1
  "...Q",
  "Q...",
  "..Q."],

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

解释: 4 皇后问题存在两个不同的解法。

解题思路

不能互相攻击图解(打X的地方不能再放置皇后)

在这里插入图片描述
看图理解,简化后的验证条件:按行遍历,第N行的皇后:

  • 同一列不能有皇后
  • 左上方不能有皇后
  • 右上方不能有皇后
问题简化

下面我们将八皇后问题转化为四皇后问题,并用回溯法来找到它的解
目的:在4x4棋盘上,使得4个皇后不能在同行同列以及同斜线上。

step1
尝试先放置第一枚皇后,被涂黑的地方是不能放皇后

step2
第二行的皇后只能放在第三格或第四格,比方我们放第三格,则:

此时我们也能理解为什么叫皇后问题了,皇后旁边容不下其他皇后。而在同一个房间放下四个皇后确实是个不容易的问题。

在这里插入图片描述

step3
可以看到再难以放下第三个皇后,此时我们就要用到回溯算法了。我们把第二个皇后更改位置,此时我们能放下第三枚皇后了。

在这里插入图片描述
step4
虽然是能放置第三个皇后,但是第四个皇后又无路可走了。返回上层调用(3号皇后),而3号也别无可去,继续回溯上层调用(2号),2号已然无路可去,继续回溯上层(1号),于是1号皇后改变位置如下,继续回溯。

在这里插入图片描述

这就是回溯算法的精髓,就是根据这个算法,最终能够把四位皇后放在4x4的棋盘里。也能用同样的方法解决了八皇后问题。下面我们用代码解决八皇后问题。

使用回溯法实现,可以套用模板,参见
使用回溯算法分割回文串

代码实现

package com.lingluo;
/**
 * @author 灵洛
 * @date 23:05 2020/3/24
 */

import java.util.ArrayList;
import java.util.List;

/**
 * @author
 * @date 2020/3/24 23:05
 */
public class N_Queens_51 {
    public List<List<String>> solveNQueens(int n) {
        // 初始化棋盘,赋初值
        char[][] board = new char[n][n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                board[i][j] = '.';
            }
        }

        List<List<String>> results = new ArrayList<List<String>>();
        backTrack(board, 0, n, results);
        return results;
    }

    private void backTrack(char[][] board, int row, int n, List<List<String>> results) {
        if (row == n) {
            // 这条路走完了,记录结果
            results.add(toList(board));
        }

        for (int col = 0; col < board[0].length; col++) {
            //枚举所有的选择
            if (!checkValidPath(board, row, col)) {
                // 路径冲突,剪枝
                continue;
            }
            // 路径不冲突,选择
            board[row][col] = 'Q';
            // 继续进行递归,row+1
            backTrack(board, row+1, n, results);
            // 撤销选择,回溯
            board[row][col] = '.';
        }
    }

    /**
     * 检查皇后之间是否不能互相攻击
     * @param board 当前棋盘情况
     * @param row 行
     * @param col 列
     * @return 满足返回true
     */
    private boolean checkValidPath(char[][] board, int row, int col) {
        int n = board[0].length;
        // 同一列不能有皇后
        for (int i = 0; i < n; i++) {
            if (board[i][col] == 'Q') {
                return false;
            }
        }
        // 左上方不能有皇后
        for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--,j--) {
            if (board[i][j] == 'Q') {
                return false;
            }
        }
        // 右上方不能有皇后
        for (int i = row - 1, j = col + 1; i >= 0 && j < n; i--,j++) {
            if (board[i][j] == 'Q') {
                return false;
            }
        }

        return true;
    }

    /**
     * char数组转成List
     * @param board
     * @return
     */
    private List<String> toList(char[][] board) {
        List<String> list = new ArrayList<String>();
        for (int i = 0; i < board[0].length; i++) {
            list.add(new String(board[i]));
        }
        return list;
    }
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值