力扣日记3.6-【回溯算法篇】51. N 皇后

news2025/6/15 19:03:01

力扣日记:【回溯算法篇】51. N 皇后

日期:2023.3.6
参考:代码随想录、力扣

51. N 皇后

题目描述

难度:困难

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

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

题解

cpp ver
class Solution {
public:
    vector<vector<string>> result;
    vector<vector<string>> solveNQueens(int n) {
        // 初始化 棋盘
        // 注意对于一个二维矩阵,board[row][col] 即索引是先row再col
        vector<string> chessboard(n, string(n, '.'));   
        backtracking(chessboard, n, 0);
        return result;
    }
    bool isValid(vector<string> chessboard, int n, int x, int y) {  // y -> row, x -> col,索引先y再x
        // 同一行是否有Q(由于是递归进入下一行,所以不可能在同一行有Q,不需判断)
        // 同一列是否有Q(由于是从上往下遍历,所以下方未遍历过的行不可能有Q,只需判断当前位置以上的部分)
        for (int i = 0; i < y; i++) {
            if (chessboard[i][x] == 'Q') return false;
        }
        // \ 是否有Q(同理,只需判断左上,注意m,k从当前位置的左上一个位置开始)
        for (int m = x - 1, k = y - 1; m >= 0 && k >= 0; m--, k--) { // m 为 横坐标,k 为纵坐标 查询:[0,x-1) [0,y-1)
            if (chessboard[k][m] == 'Q') return false;
        }
        // / 是否有Q(同理,只需判断右上,注意m,k从当前位置的右上一个位置开始)
        for (int m = x + 1, k = y - 1; m < n && k >= 0; m++, k--) { // [x+1, n) [0,y-1)
            if (chessboard[k][m] == 'Q') return false;
        }
        return true;
    }
    // 关键:将N皇后问题转换为树形结构:横向搜索为for循环,纵向遍历(进入下一行)为递归
    // 参数:棋盘矩阵,皇后数,当前遍历到的行数
    void backtracking(vector<string>& chessboard, int n, int row) {
        // 终止条件:row从0开始,当为n时,说明已经遍历完所有行
        if (row == n) {
            result.push_back(chessboard);
            return;
        }
        // for 循环
        for (int i = 0; i < n; i++) {   // 每一行都从0开始遍历
            if (isValid(chessboard, n, i, row)) {
                // 如果当前位置为有效位置
                // 设置此位置为皇后位置
                chessboard[row][i] = 'Q';
                // 递归(进入下一行)
                backtracking(chessboard, n, row + 1);   // row 作为参数,自动回溯
                // 回溯
                chessboard[row][i] = '.';
            }
        }
    }   
};

复杂度

时间复杂度: O(n!)
空间复杂度: O(n)

思路总结

  • 第一次接触到N皇后,即使知道用回溯法,还是不知道如何下手。再次感谢代码随想录提供思路。
  • 关键思路:
    • 将N皇后问题转换为树形结构:依次遍历棋盘的各个位置,横向搜索通过for循环,纵向遍历(进入下一行)通过递归

      棋盘的宽度就是for循环的长度,递归的深度就是棋盘的高度

    • 只有当前位置有效,才能放入棋盘(处理节点)并进行递归回溯

  • 难点(易错):判断当前位置是否有效
    • 首先要明确,对于二维数组,row为第一个索引,col为第二个索引
    • 判断当前位置是否有效,即当前位置的同一行、同一列、左45°、右45°(同斜线)均不能出现皇后’Q’
    • 剪枝:由于遍历是从左到右、从上往下(一行接一行)遍历,所以在判断时:
      • 对于同一行是否有Q:由于是递归进入下一行,所以不可能在同一行有Q,不需判断
      • 对于同一列是否有Q:由于是从上往下遍历,所以下方未遍历过的行不可能有Q,只需判断当前位置以上的部分
      • 对于 \ 方向是否有Q:同理,只需判断左上,注意m(横坐标),k(纵坐标)从当前位置的左上一个位置开始,即m:x-1 → 0,k:y-1 → 0;
      • 对于 / 方向是否有Q:同理,只需判断右上,注意m,k从当前位置的右上一个位置开始,即 m:x+1 → n - 1,k:y -1 → 0。
  • 三部曲:
    • 参数: 棋盘矩阵,皇后数,当前遍历到的行数
      • 棋盘的初始化:
        vector<string> chessboard(n, string(n, '.'));
        
    • 终止条件:row从0开始,当为n时,说明已经遍历完所有行,则终止
    • for 循环
      • 对棋盘的第row行,从棋盘左遍历到右
      • 如果当前位置有效,则进行:
        • 处理节点即放下皇后(chessboard[row][i] = 'Q';
        • 递归(进入下一行)
        • 回溯(chessboard[row][i] = '.';
  • 树状结构示意图(n = 3)
    • 在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1503953.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

008-slot插槽

slot插槽 1、插槽 slot 的简单使用2、插槽分类2.1 默认插槽2.2 具名插槽2.3 作用域插槽 插槽就是子组件中的提供给父组件使用的一个占位符&#xff0c;用<slot></slot> 表示&#xff0c;父组件可以在这个占位符中填充任何模板代码&#xff0c;如 HTML、组件等&…

【PHP+代码审计】PHP基础——数据类型

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【Java、PHP】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收…

【滑动窗口】力扣239.滑动窗口最大值

前面的文章我们练习数十道 动态规划 的题目。相信小伙伴们对于动态规划的题目已经写的 得心应手 了。 还没看过的小伙伴赶快关注一下&#xff0c;学习如何 秒杀动态规划 吧&#xff01; 接下来我们开启一个新的篇章 —— 「滑动窗口」。 滑动窗口 滑动窗口 是一种基于 双指…

【大模型系列】根据文本检索目标(DINO/DINOv2/GroundingDINO)

文章目录 1 DINO(ICCV2021, Meta)1.1 数据增强1.2 损失函数 2 DINOv2(CVPR2023, Meta)2.1 数据采集方式2.2 训练方法 3 Grounding DINO3.1 Grounding DINO设计思路3.2 网络结构3.2.1 Feature Extraction and Enhancer3.2.2 Language-Guided Query Selection3.2.3 Cross-Modalit…

云原生构建 微服务、容器化与容器编排

第1章 何为云原生&#xff0c;云原生为何而生 SOA也就是面向服务的架构 软件架构的发展主要经历了集中式架构、分布式架构以及云原生架构这几代架构的发展。 微服务架构&#xff0c;其实是SOA的另外一种实现方式&#xff0c;属于SOA的子集。 在微服务架构下&#xff0c;系统…

sign加密方法生成

1. 引入包的问题 2. 原因 .pycrypto、pycrytodome和crypto是一个东西&#xff0c;crypto在python上面的名字是pycrypto&#xff0c;它是一个第三方库&#xff0c;但是已经停止更新 3. 解决方法 --直接安装&#xff1a;pip install pycryptodome 3.但是&#xff0c;在使用的时…

【C++进阶】哈希的应用 --- 布隆过滤器

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前学习C和算法 ✈️专栏&#xff1a;C航路 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞&#x1…

【leetcode】429. N 叉树的层序遍历

题目描述 给定一个 N 叉树&#xff0c;返回其节点值的_层序遍历_。&#xff08;即从左到右&#xff0c;逐层遍历&#xff09;。 树的序列化输入是用层序遍历&#xff0c;每组子节点都由 null 值分隔&#xff08;参见示例&#xff09;。 示例 1&#xff1a; 输入&#xff1a;…

BUUCTF-Misc6

数据包中的线索1 1.打开附件 发现是一个流量包 2.Wireshark 用Wireshark打开 右键属性&#xff0c;追踪tcp流&#xff0c;发现base64编码 3.base64转图片 将base64编码保存为文本文档 Python脚本 import os,base64 with open("/root/桌面/3/1.txt","r"…

基于SpringBoot+MYSQL的网上订餐系统

目录 1、 前言介绍 2、主要技术 3、系统功能分析 3.1、用户功能分析 3.2、管理员功能分析 4、系统结构分析 4.1、逻辑结构 4.2、物理结构 5、数据库设计 5.1、数据库E-R图设计 5.2、数据库表设计 6、运行截图(部分) 6.1、用户功能模块的实现 6.2、管理员功能模块的…

项目管理【引论一】项目管理的目标和高层次目标

系列文章目录 【引论一】项目管理的目标和高层次目标 一、项目管理的目标 项目管理的目标是在规定的时间内&#xff0c;在批准的预算内&#xff0c;完成事先确定的工作范围内的工作&#xff0c;并且达到预期的质量性能要求。 1.时间、成本和质量之间的关系 1.1时间、成本和…

YOLOv8.1.0安装

【YOLO】YOLOv8训练环境配置 python 3.8.18 cuda 11.3.1 cudnn 8.2.1 pytorch 1.12.1-gpu版 - 知乎 (zhihu.com) 一、Anaconda 默认装好了可用的Anaconda&#xff0c;安装教程见Win10系统anaconda安装 - 知乎 (zhihu.com) 二、在虚拟环境下用conda安装 1.创建虚拟环境 …

transformer--使用transformer构建语言模型

什么是语言模型? 以一个符合语言规律的序列为输入&#xff0c;模型将利用序列间关系等特征&#xff0c;输出一个在所有词汇上的概率分布.这样的模型称为语言模型. # 语言模型的训练语料一般来自于文章&#xff0c;对应的源文本和目标文本形如: src1"Ican do",tgt1…

Python快速入门系列-2(Python的安装与环境设置)

第二章&#xff1a;Python的安装与环境设置 2.1 Python的下载与安装2.1.1 访问Python官网2.1.2 安装Python对于Windows用户对于macOS用户对于Linux用户 2.2 集成开发环境&#xff08;IDE&#xff09;的选择与设置2.2.1 PyCharm2.2.2 Visual Studio Code2.2.3 Jupyter Notebook2…

连锁门店终端如何高效IT运维?向日葵助力服装行业数字化升级

服装行业作为典型的传统行业&#xff0c;因供应逐渐饱和、产能相对过剩以及消费结构升级&#xff0c;其销售端的数字化转型需求是最为迫切的。 为此&#xff0c;某知名时装品牌紧抓数字化转型机遇&#xff0c;在2016年起就开始了数字化变革&#xff0c;并在两年多的时间里完成…

关于Spring依赖注入简洁方式的探索

最近在项目开发过程中关注到一个依赖注入的写法差异&#xff0c;因为本人代码上有点强迫症&#xff0c;看到这种不同人不一样的写法&#xff0c;特意了解了一下&#xff0c;但是依然有部分疑惑未解。 两种写法&#xff1a;(就是传说中最常见的属性注入和构造函数注入) Service…

菜鸟笔记-14Python绘图颜色使用

Python中绘图主要依赖于各种库&#xff0c;其中matplotlib是最常用且功能强大的一个。在matplotlib中&#xff0c;你可以使用各种颜色来表示不同的数据点、线条或填充区域。下面我将详细介绍如何在Python中使用matplotlib来设置绘图颜色&#xff0c;并给出具体的例子。 14.1颜…

DFS回溯-经典全排列问题(力扣)

前言 对于全排列问题&#xff0c;常用的做法是设置一个vis数组来确定位置i上的数字是否被访问&#xff0c;因为是全排列问题&#xff0c;所以不同的顺序也是不一样的排列&#xff0c;因此每次都是从起点开始询问**(注意起点到底是0还是1)** 46全排列(最简单的模板) class So…

训练验证码之ddddocr一个图文视频教学

目录 一、推荐文章视频一、ddddocr环境配置二、字符集验证码训练三、ocr_api_server服务搭建 一、推荐文章视频 文章原文来自这里&#xff1a;训练验证码-4、ddddocr训练字符验证码 &#xff0c; 原文文章末尾有视频介绍更多内容见训练验证码合集 一、ddddocr环境配置 1.打开…

【C++专栏】C++入门 | 函数重载、引用、内联函数

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;C专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ C入门 | 函数重载、引用、内联函数 文章编号&#xff1a;C入门 / 02 文…