leetcode| 51. N皇后问题

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


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

给定一个整数 n,返回 n 皇后不同的解。

示例:
输入: 4
解释: 4 皇后问题存在如下两个不同的解法。
[
?[".Q..", ?// 解法 1
? "...Q",
? "Q...",
? "..Q."],

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

n皇后问题有两种解的要求,一种仅要求输出解决方案个数,一种要求输出所有的具体解决方案。

思路

暴力破解不可行,时间复杂度为O(n^n)。
回溯法,其中在进行深搜时,剪枝的关键在于:

  • 对于任意一点(x,y),其所在的主对角线(\)和副对角线(/)上的坐标点,分别满足一定关系。
  • n*n的矩阵,\型对角线和/型对角线分别有2n-1条。
  • 任意一条\型对角线上的坐标点满足 row-col=常量a ,且a的范围为-(n-1)到n-1。
  • 任意一条/型对角线上的坐标点满足 row+col=常量b ,且b的范围为0到2n-2。
  • 如4*4矩阵
  • 使用一维数组x,y,z可以分别标记\、/和纵方向是否已有棋子(按行放置棋子,无需再考虑横向)。

每一行放置时,相比于上一行能放置棋子的空位就会少1,时间复杂度O(n!),空间复杂度O(n)。

仅求解决方案个数代码

class Solution {
    public int dfs_backtrace(int row, int count, int n, int[] z, int[] x, int[] y) {
        //每一层递归携带了row参数,所以每个dfs_backtrace函数代表row行在尝试放置棋子
        //因此只需一层for循环遍历row行的每一列
        for(int col = 0; col < n; col++){
            //如果各个方向都没有标记,说明此处可以放置棋子
            if(z[col] + x[n + row - col] + y[row + col] == 0) {
                //标记
                z[col] = 1;
                x[n + row - col] = 1;
                y[row + col] = 1;
                //dfs
                if(row + 1 == n) {
                    count++;
                } else {
                    count = dfs_backtrace(row+1, count, n, z, x, y);
                }
                //回溯
                z[col] = 0;
                x[n + row -col] = 0;
                y[row + col] = 0;
            }
        }
        return count;
    }

    public int totalNQueens(int n) {
        int[] z = new int[n];    // z[i]表示第i列是否有棋子
        int[] x = new int[2*n];  // x[n + row - col]表示(row,col)点所在主对角线(\)是否有棋子
        int[] y = new int[2*n];  // y[row + col]表示(row,col)点所在副对角线(/)是否有棋子
        return dfs_backtrace(0, 0, n, z, x, y);
    }
}

求出所有解决方案的代码

仅需要添加一个queue[n]数组,queue[i] = j, 表示为第i行的皇后放置在第j列;
将queue在放棋子与撤销棋子时同步更新即可,引入queue数组是为了记录皇后位置,用于输出解决方案。
以下代码与上个代码思路完全一致,仅将一些过程写成了函数。

class Solution {
    int n;
    int[] x;
    int[] y;
    int[] z;
    int[] queue;

    List<List<String>> output = new ArrayList<List<String>>();

    private boolean is_not_attack(int row, int col) {
        return x[n+row-col]+y[row+col]+z[col] == 0;
    }

    private void placeQueue(int row, int col) {
        x[n + row - col] = 1;
        y[row + col] = 1;
        z[col] = 1;
        queue[row] = col;
    }

    private void removeQueue(int row, int col) {
        x[n + row - col] = 0;
        y[row + col] = 0;
        z[col] = 0;
        queue[row] = 0;
    }

    private void addOutput() {
        List<String> list = new ArrayList<String>();
        for(int i = 0; i < n; i++) {
            char[] str = new char[n];
            Arrays.fill(str, '.');
            str[queue[i]] = 'Q';
            list.add(new String(str));
        }
        output.add(list);
    }

    private void traceback(int row) {
        for(int col = 0; col < n; col++) {
            if(is_not_attack(row, col)) {
                //放置棋子
                placeQueue(row, col);
                //DFS
                if(row + 1 == n) {
                    addOutput();
                } else {
                    traceback(row + 1);
                }
                //回溯棋子
                removeQueue(row, col);
            }
        }
    }

    public List<List<String>> solveNQueens(int n) {
        this.n = n;
        x = new int[2*n];
        y = new int[2*n];
        z = new int[n];
        queue = new int[n];
        traceback(0);
        return output;
    }
}

笔记

方阵主副对角线行列值的特殊关系。

递归:算法结构,函数调用自身。
回溯:算法思想,会“剪枝”的穷举。
DFS:回溯搜索是深度优先搜索的一种,回溯法在搜索过程中不保留完整树结构,DFS搜索树结构完整。

链接:https://leetcode-cn.com/problems/n-queens
链接:https://leetcode-cn.com/problems/n-queens-ii

原文地址:https://www.cnblogs.com/ustca/p/12300045.html

时间: 2024-11-06 15:43:42

leetcode| 51. N皇后问题的相关文章

[leetcode]51. N-QueensN皇后

The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other. Given an integer n, return all distinct solutions to the n-queens puzzle. Each solution contains a distinct board configuration of

Leetcode 51. N皇后

class Solution { public: //最后返回的结果 vector<vector<string>> ans; // 记录路径的信息,path的索引表示的第几列,因此对应的值就是第几行,这样才可以确定一个唯一的二维坐标 vector<int> path; // 标志记录信息 vector<bool> row; vector<bool> diagonal ; vector<bool> back_diagonal ; //

[LeetCode系列]N皇后问题递归解法 -- 位操作方式

N皇后问题: 给定8*8棋盘, 放置n个皇后, 使其互相不能攻击(即2个皇后不能放在同一行/列/正反对角线上), 求解共有多少种放置方式? 这个问题的解答网上有不少, 但是位操作解法的我看到的不多. 下面贴出代码和图解, 也就不赘述了. 1 class Solution { 2 public: 3 /* 使用位操作实现的回溯算法. 按行扫描, 检测可以放置的列. 4 * 'limit' - 都是 '1'. 代表着所有列都被占据了 5 * 'h' - 是目前所有皇后列在行上的垂直投影. 如果 h=

leetcode之n皇后问题

leetcode上有两个关于n皇后的问题,两个题目基本是一样的,只是第二个是把所有的排法求出来.n皇后最简单的就是用递归,每次判断一行的一个位置,如果合法,就判断下一行,不合法再判断下一个位置 N-Queens II Follow up for N-Queens problem. Now, instead outputting board configurations, return the total number of distinct solutions. class Solution {

leetCode 51. N-Queens | 回溯问题(N皇后问题) | hard

51. N-Queens The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other. Given an integer n, return all distinct solutions to the n-queens puzzle. Each solution contains a distinct board conf

leetCode 51.N-Queens (n皇后问题) 解题思路和方法

N-Queens The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other. Given an integer n, return all distinct solutions to the n-queens puzzle. Each solution contains a distinct board configur

[LeetCode 51&amp;52] N-Queens I &amp; II (N皇后问题)

题目链接:n-queens import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other. Given an integer n, return all dist

LeetCode 51 N-Queens II

Follow up for N-Queens problem. Now, instead outputting board configurations, return the total number of distinct solutions. 思路1:打表 public class Solution { public int totalNQueens(int n) { int[] result = new int[] { 0, 1, 0, 0, 2, 10, 4, 40, 92, 352,

[LeetCode]N-Queens 八皇后问题扩展(经典深搜)

The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other. Given an integer n, return all distinct solutions to the n-queens puzzle. Each solution contains a distinct board configuration of