leetcode51.N皇后(困难)-回溯法

2024-04-30 00:44

本文主要是介绍leetcode51.N皇后(困难)-回溯法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 思路

都知道n皇后问题是回溯算法解决的经典问题,但是用回溯解决多了组合、切割、子集、排列问题之后,遇到这种二维矩阵还会有点不知所措。

首先来看一下皇后们的约束条件:

  1. 不能同行
  2. 不能同列
  3. 不能同斜线

确定完约束条件,来看看究竟要怎么去搜索皇后们的位置,其实搜索皇后的位置,可以抽象为一棵树。

下面我用一个 3 * 3 的棋盘,将搜索过程抽象为一棵树,如图:

 从图中,可以看出,二维矩阵中矩阵的高就是这棵树的高度,矩阵的宽就是树形结构中每一个节点的宽度。

那么我们用皇后们的约束条件,来回溯搜索这棵树,只要搜索到了树的叶子节点,说明就找到了皇后们的合理位置了

然后套用递归三部曲解决。

  • 递归函数参数
  • 递归终止条件
  • 单层搜索的逻辑

这里还要外加一个 :验证棋盘是否合法

按照如下标准去重:

  1. 不能同行
  2. 不能同列
  3. 不能同斜线 (45度和135度角)

 java版本代码:

class Solution {List<List<String>> res = new ArrayList<>(); //全局变量res集合,用于存储解决方案的列表// 解决N皇后问题的方法,返回解决方案的集合public List<List<String>> solveNQueens(int n) {char[][] chessboard = new char[n][n]; // 创建一个N*N的字符棋盘for (char[] c : chessboard) {Arrays.fill(c, '.'); // 初始化棋盘,填充为'.'}backTrack(n, 0, chessboard); // 调用回溯方法,开始搜索解决方案return res; // 返回所有解决方案的集合}// 回溯方法,用于搜索解决N皇后问题的解决方案// n 为输入的棋盘大小// row 是当前递归到棋盘的第几行了public void backTrack(int n, int row, char[][] chessboard) {if (row == n) { // 终止条件:如果已经填满了所有行,即找到了一种解决方案res.add(Array2List(chessboard)); // 将当前棋盘状态添加到解决方案的集合中(list集合里的元素还是个集合list,见示例)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] = '.'; // 回溯,撤销当前位置的皇后(把Q替换成 .即可)}}}// 将二维字符数组转换为字符串集合public List Array2List(char[][] chessboard) {List<String> list = new ArrayList<>(); // 创建一个空集合for (char[] c : chessboard) { // 遍历棋盘的每一行 字符数组:char[] c,eg:{"Q",".",".",".",} 、list.add(String.copyValueOf(c)); // 将当前行的字符数组char[] c 转换为字符串并添加到集合list中}return list; // 返回转换后的集合 eg:[".Q..","...Q","Q...","..Q."]}// 检查当前位置是否可以放置皇后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; // 返回false,表示当前位置不能放置皇后}}// 检查45度对角线上是否已经放置了皇后for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) { // 向左上方遍历if (chessboard[i][j] == 'Q') { // 如果当前位置左上方有皇后return false; // 返回false,表示当前位置不能放置皇后}}// 检查135度对角线上是否已经放置了皇后for (int i = row - 1, j = col + 1; i >= 0 && j <= n - 1; i--, j++) { // 向右上方遍历if (chessboard[i][j] == 'Q') { // 如果当前位置右上方有皇后return false; // 返回false,表示当前位置不能放置皇后}}return true; // 如果以上条件都不满足,表示当前位置可以放置皇后,返回true}
}

这篇关于leetcode51.N皇后(困难)-回溯法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/947570

相关文章

题目1254:N皇后问题

题目1254:N皇后问题 时间限制:1 秒 内存限制:128 兆 特殊判题:否 题目描述: N皇后问题,即在N*N的方格棋盘内放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在同一斜线上。因为皇后可以直走,横走和斜走如下图)。 你的任务是,对于给定的N,求出有多少种合法的放置方法。输出N皇后问题所有不同的摆放情况个数。 输入

回溯——9.全排列

力扣题目链接 给定一个 没有重复 数字的序列,返回其所有可能的全排列。 示例: 输入: [1,2,3]输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ] 解题思路 问题建模:题目要求给出一个数组的所有排列组合,属于典型的全排列问题,这可以用回溯法来解决。回溯法通过递归的方式,依次将数组中的每个元素放入排列中,直到生成

代码训练营 Day26 | 47.排序II | 51. N-皇后 |

47.排序II 1.跟46题一样只不过加一个树层去重 class Solution(object):def backtracking(self,nums,path,result,used):# recursion stopif len(path) == len(nums):# collect our setresult.append(path[:])return for i in range(

风控系统之指标回溯,历史数据重跑

个人博客:无奈何杨(wnhyang) 个人语雀:wnhyang 共享语雀:在线知识共享 Github:wnhyang - Overview 回顾 默认你已经看过之前那篇风控系统指标计算/特征提取分析与实现01,Redis、Zset、模版方法。 其中已经介绍了如何利用redis的zset结构完成指标计算,为了方便这篇文章的介绍,还是在正式开始本篇之前回顾一下。 时间窗口 zset

165-Stamps【回溯】

回溯 给h和k的意思是在k种邮票中选h个邮票 基本的连续邮资问题 15226160 165 Stamps Accepted C++ 0.062 2015-03-27 07:21:37 #include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn = 2

JAVA学习-练习试用Java实现“N皇后 II”

问题: n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。 给定一个整数 n ,返回 n 皇后问题不同的解决方案的数量。 示例 1: 输入:n = 4 输出:2 解释:如上图所示,4 皇后问题存在两个不同的解法。 示例 2: 输入:n = 1 输出:1 提示: 1 <= n <= 9 皇后彼此不能相互攻击,也就是说:任何两个皇后都不能处于同

回溯——8.递增子序列

力扣题目链接 给定一个整型数组, 你的任务是找到所有该数组的递增子序列,递增子序列的长度至少是2。 示例: 输入: [4, 6, 7, 7]输出: [[4, 6], [4, 7], [4, 6, 7], [4, 6, 7, 7], [6, 7], [6, 7, 7], [7,7], [4,7,7]] 说明: 给定数组的长度不会超过15。数组中的整数范围是 [-100,100]。给定数组中

【代码随想录|回溯part04】

代码随想录|回溯part04 1、46.全排列2、47.全排列 II3.问题 总结 python 1、46.全排列 46.全排列 class Solution:def permute(self, nums):result = []self.backtracking

代码随想录算法训练营第十九天| 回溯理论、77. 组合、216. 组合总和Ⅲ、17. 电话号码的字母组合

今日内容 回溯的理论基础leetcode. 77 组合leetcode. 216 组合总和Ⅲleetcode. 17 电话号码的字母组合 回溯理论基础 回溯法也叫回溯搜索法,它是一种搜索的方式,而且只要有递归就会有回溯,回溯就是递归的副产品。 回溯说到底并不是什么非常高深的搜索方式,本质上仍然是穷举,穷举所有可能然后选择出我们要的答案。剪枝会使回溯法更加高效一点,但改变不了回溯本质就是穷举

笔试,牛客.kotori和n皇后​,牛客.AOE还是单体

目录 牛客.kotori和n皇后​编辑 牛客.AOE还是单体 牛客.kotori和n皇后  想起来,我之前还写过n皇后的题,但是这个我开始只能想到暴力解法 判断是不是斜对角线,联想y=x+b和y=-x+b,假如在一条线上,那么他们的x和y会对应成比例,这个扫描+判断是一个O(n^2)的操作。 import java.util.*; import java.io.*;//