首页 > 其他分享 >代码随想录第30天|51. N皇后

代码随想录第30天|51. N皇后

时间:2024-04-04 22:04:09浏览次数:22  
标签:int 随想录 chessboard 30 51 char 皇后 col row

51. N皇后

51. N 皇后 - 力扣(LeetCode)

代码随想录 (programmercarl.com)

这就是传说中的N皇后? 回溯算法安排!| LeetCode:51.N皇后_哔哩哔哩_bilibili

按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。

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

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

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

示例 1:

输入:n = 4
输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
解释:如上图所示,4 皇后问题存在两个不同的解法。

示例 2:

输入:n = 1
输出:[["Q"]]

提示:

  • 1 <= n <= 9

其实回溯算法搜索过的位置就是一个棋盘。

 回溯三部曲:

1、确定参数: 

定义全局变量二维数组result来收集最终结果,n是棋盘的大小,row来记录遍历到棋盘第几层:

public void backTrack(int n, int row, char[][] chessboard) {

}

2、确定终止条件:

当棋盘递归到叶子节点的时候,说明找到了一个符合条件的结果,收集叶子节点的值并返回:

// 如果当前行数等于 n,说明找到了一个解,将其转换为字符串列表并添加到结果列表中
        if (row == n) {
            res.add(Array2List(chessboard));
            return;

 3、确定单层搜索的逻辑:

// 遍历当前行的所有列
        for (int col = 0; col < n; ++col) {
            // 如果当前位置可以放置皇后
            if (isValid(row, col, n, chessboard)) {
                // 在当前位置放置皇后
                chessboard[row][col] = 'Q';
                // 继续向下一行搜索
                backTrack(n, row + 1, chessboard);
                // 回溯,将当前位置重新设为 '.'
                chessboard[row][col] = '.';
            }
        }

验证棋盘是否符合要求:

1、皇后不能同行

2、皇后不能同列

3、不能同斜线

 // 定义一个公有方法 isValid,用于检查当前位置是否可以放置皇后
    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;
    }

综合代码:

// 定义一个名为 Solution 的类
class Solution {
    // 声明一个成员变量 res,类型为 List<List<String>>,用于存储解决N皇后问题的结果
    List<List<String>> res = new ArrayList<>();

    // 定义一个公有方法 solveNQueens,接收一个整数参数 n,返回解决N皇后问题的结果
    public List<List<String>> solveNQueens(int n) {
        // 创建一个大小为 n*n 的字符数组表示棋盘,初始化为 '.'
        char[][] chessboard = new char[n][n];
        for (char[] c : chessboard) {
            Arrays.fill(c, '.');
        }
        // 调用 backTrack 方法进行回溯搜索解决N皇后问题
        backTrack(n, 0, chessboard);
        // 返回解决N皇后问题的结果
        return res;
    }

    // 定义一个公有方法 backTrack,用于回溯搜索解决N皇后问题
    public void backTrack(int n, int row, char[][] chessboard) {
        // 如果当前行数等于 n,说明找到了一个解,将其转换为字符串列表并添加到结果列表中
        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);
                // 回溯,将当前位置重新设为 '.'
                chessboard[row][col] = '.';
            }
        }
    }

    // 定义一个公有方法 Array2List,用于将字符数组转换为字符串列表
    public List Array2List(char[][] chessboard) {
        List<String> list = new ArrayList<>();
        // 将字符数组转换为字符串并添加到列表中
        for (char[] c : chessboard) {
            list.add(String.copyValueOf(c));
        }
        return list;
    }

    // 定义一个公有方法 isValid,用于检查当前位置是否可以放置皇后
    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;
    }
}

标签:int,随想录,chessboard,30,51,char,皇后,col,row
From: https://blog.csdn.net/lilith_2001/article/details/137382014

相关文章

  • 代码随想录第29天|491.递增子序列 46.全排列 47.全排列 II
    目录:491.递增子序列46.全排列47.全排列II 491.递增子序列491.非递减子序列-力扣(LeetCode)代码随想录(programmercarl.com)回溯算法精讲,树层去重与树枝去重|LeetCode:491.递增子序列_哔哩哔哩_bilibili给你一个整数数组 nums ,找出并返回所有该数组中不同的递......
  • 代码随想录算法训练营第一天 | 704.二分查找、27.移除元素
    704.二分查找文档讲解:代码随想录(https://www.programmercarl.com/)视频讲解:https://www.bilibili.com/video/BV1fA4y1o715/状态:704有思路但是不完善题目给定一个n个元素有序的(升序)整型数组nums和一个目标值target,写一个函数搜索nums中的target,如果目标值存在返回下......
  • 挑战程序设计竞赛 2.6章习题 POJ 1930 Dead Fraction
    https://vjudge.csgrandeur.cn/problem/POJ-1930迈克在最后一刻拼命地赶着完成他的论文。在接下来的3天里,他需要将所有的研究笔记整理成较为连贯的形式。不幸的是,他注意到他在计算方面非常粗心。每当他需要进行算术运算时,他只是将其输入计算器,并将他认为相关的答案写下来。每当......
  • UOJ #514. 【UR #19】通用测评号
    Description有\(n\)个管道,每个管道的最大大小为\(a\),每次等概率随机选一个没满的管道里放一个石子,当所有管道的大小都\(\geqb\)时停止,问装满的管道的期望个数,与\(998244353\)取模。\(1\len\le250,1\leb<a\le250\)。Solution先考虑一个引理:有\(n\)个集合,有......
  • 2024.3.30 模拟赛
    A数列删除至少删除\(m\)个数,意思就是最多保留\(n-m\)个数。删除的总和最小,意思就是保留的总和最大。非降子序列问题可以用经典的动态规划来解决。用\(f[i][j]\)表示,当前选的最后一个数是\(a[i]\),一共选了\(j\)个数,选的数总和最大是多少。转移就是枚举上一个数\(a[......
  • P4551 最长异或路径
    原题链接题解1.任意两点间的异或和等于他们到根节点的异或和的异或,令每个点到根节点的异或值为\(path[i]\)2.建立01字典树,塞入所有\(path[i]\)然后遍历每个点,找出每个点异或最大对应的点3.如何找?往当前\(path[i]\)的每一位相反的方向移动code#include<bits/stdc++.h>u......
  • 代码随想录算法训练营第二十一天| 530. 二叉搜索树的最小绝对差 501. 二叉搜索树中的
    530.二叉搜索树的最小绝对差https://leetcode.cn/problems/minimum-absolute-difference-in-bst/description/TreeNodepre=null;intres=Integer.MAX_VALUE;publicintgetMinimumDifference(TreeNoderoot){if(root==null)return0;pr......
  • 代码随想录DAY1 | 二分,双指针移除元素
    代码随想录DAY1|二分,双指针移除元素题目描述给定一个n个元素有序的(升序)整型数组nums和一个目标值target,写一个函数搜索nums中的target,如果目标值存在返回下标,否则返回-1。示例1:输入:nums=[-1,0,3,5,9,12],target=9输出:4解释:9出现在nums中并且......
  • 代码随想录算法训练营第一天 | 数组 704.二分查找 27.移除元素
    leetcode704.二分查找题目704.二分查找给定一个n个元素有序的(升序)整型数组nums和一个目标值target,写一个函数搜索nums中的target,如果目标值存在返回下标,否则返回-1。解题思路代码实现本题对自己的难点有大概的解题思路,但是代码实现有几个点写不出来1、怎么取......
  • 30 天精通 RxJS (08):简易拖拉实作 - take, first, takeUntil, concatAll
    我们今天要接着讲take,first,takeUntil,concatAll这四个operators,并且实作一个简易的拖拉功能。Operatorstaketake是一个很简单的operator,顾名思义就是取前几个元素后就结束,范例如下varsource=Rx.Observable.interval(1000)varexample=source.take(3)example.......