N皇后问题详解

news2024/11/25 20:32:46

文章目录

    • 一、题目描述
    • 二、题目解析
      • (1)思考一(集合+回溯)
      • (2)思考二(数组+深度递归)
      • (3)思考三(位运算)

一、题目描述

N 皇后问题是指在 n * n 的棋盘上要摆 n 个皇后,
要求:任何两个皇后不同行不同列不在同一条斜线上,
求给一个整数 n ,返回 n 皇后的摆法数。

数据范围: 1 ≤ n ≤ 9

例如当输入4时,对应的返回值为2,对应的两种四皇后摆位如下图所示:

在这里插入图片描述

二、题目解析

(1)思考一(集合+回溯)

变量罗列:

  • i:行号
  • j:列号
  • set1:保存已经被占用的列
  • set2:保存已经被占用的左斜线(横纵坐标相加确定一条左斜线)
  • set3:保存已经被占用的右斜线(横纵坐标相减确定一条右斜线)
  • result :摆放数

思路分析:

将从第 0 行开始放皇后,放成功后再放第 1 行,保证皇后们都不在同一行上

在第 i 行寻找放皇后的位置时,将会依次从第 0 列尝试到第 n-1 列,尝试着将皇后放在坐标 (i,j)上,如果 set1 中没有包含 j,set2 中没有包含 i+j,set3 中没有包含 i-j,皇后放置成功

第 i 行的皇后放成功后,就可以开始放第 i+1 行的皇后,直到 i == n ,棋盘上成功多出了一种摆放法,result 加一

返回后就回溯,撤掉刚才摆放好的皇后,尝试下一列,没有下一列说明当前方法执行完毕,返回了

代码展示:

public class Solution {
    public HashSet<Integer> set1 = new HashSet<>();//列
    public HashSet<Integer> set2 = new HashSet<>();//正斜线
    public HashSet<Integer> set3 = new HashSet<>();//反斜线
    public int result = 0;
    public int Nqueen (int n) {
        func(0,n);//表示从第0行开始放,一共有n行
        return result;
    }
    public void func(int i,int n) {
        if(i == n) {
            //放好了
            result++;
            return;
        }
        //在第i行中依次找到一个合适的列放皇后
        for(int j = 0;j < n;j ++) {
            if(set1.contains(j) || set2.contains(i+j) || set3.contains(i-j)) {
                continue;//都是不符合条件的
            }
            set1.add(j);
            set2.add(i+j);
            set3.add(i-j);
            //放好了,尝试下一行
            func(i+1,n);
            //恢复原样
            set1.remove(j);
            set2.remove(i+j);
            set3.remove(i-j);
        }
    }
}

(2)思考二(数组+深度递归)

变量罗列:

  • i:行号
  • j:列号
  • board数组:board[i] 表示第 i 行放皇后的列号
  • result :摆放数

思路分析:

和思路一的区别在于使用一个数组代替三个 set 集合

在第 i 行放置皇后时,第 0 行到第 i-1 行都放好皇后,board[0~i-1] 上的值都有效,符合题目的限定条件

在判断坐标(i,j)位置是否能够放皇后时,如果board[k] (0 ≤ k ≤ i-1) 的值等于 j ,说明和第 k 行的皇后重行。如果 board[k] 和 j 差的绝对值等于 k 和 i 差的绝对值,说明坐标 (i,j)和坐标(k,board[k])相连后和水平呈45度角,即在同一条斜线上(包含左斜线和右斜线)

将第 i 行上所有可以放置皇后的列所包含的摆法数累加,并返回

代码展示:

public class Solution1 {
    public int Nqueen (int n) {
        int[] board = new int[n];//表示棋盘
        //board[i]表示第i行放皇后的列,board[2] = 3 表示第二行的皇后放在了第3列上
        return func(0,board,n);//表示从第0行开始往下摆皇后
    }
    public int func(int i,int[] board,int n) {
        //准备开始摆第i行的皇后
        //此时board[0~i-1]都已经有了有效值,即0~i-1行上都符合规则的放好了皇后
        if(i == n) {
            //到达终止行,即棋盘最后一行也摆好了皇后
            return 1;
        }
        int result = 0;
        //对第i行上所有符合条件可以放皇后的列的方法数进行累加
        for(int j = 0;j < n;j ++) {
            if(isOK(board,i,j)) {
                //可以放皇后,深度递归
                board[i] = j;
                result += func(i+1,board,n);
            }
        }
        return result;
    }
    //就是来验证第i行第j列是否能放皇后
    public boolean isOK(int[] board,int i,int j) {
        for(int k = 0;k < i;k ++) {
            if(board[k] == j || Math.abs(board[k]-j) == Math.abs(k-i)) {
                return false;//不符合条件
            }
        }
        return true;
    }
}

(3)思考三(位运算)

以上两种方法的时间复杂度都是 O(n!) ,空间复杂度为 O(n),指标已经是没有办法优化了,但是可以通过位运算进行常数时间的优化,优化的目的就是省去依次判断和过去放过的皇后有重列或者重斜线的步骤

变量罗列:

  • limit:表示位的限制,该值的后 n 位为 1 (若为7皇后,limit为0… 0111 1111)
  • colLim:表示列的限制,1表示已经放了皇后,0表示没有放过皇后
  • leftLim:表示左斜线的限制,1表示已经放了皇后,0表示没有放过皇后
  • rightLim:表示右斜线的限制,1表示已经放了皇后,0表示没有放过皇后
  • pos:可以放皇后的位置,1表示可以放皇后,0表示不能放皇后
  • lastOneIndex:pos最右侧的1的权值

思路分析:

以 8 皇后进行举例:

如果 colLim 后 8 位都是 1(等于limit),说明棋盘上所有的列都放上了皇后,摆放数加一

假设第 0 行的皇后放在了第 5 列

在这里插入图片描述

此时的 pos 值有 5 个 1,代表只有这 5 列还可以放皇后,通过 pos & (~pos + 1) 就可以求的最右侧的 1的权值(lastOneIndex),将皇后放到此处,pos 减去权值,直到 pos 为 0 说明 5 个放皇后的地方都尝试过了,累加摆放数

在这里插入图片描述

在这里插入图片描述

代码展示:

public class Solution2 {
    //限制:只能是1~32皇后
    public int Nqueen (int n) {
        // write code here
        if (n < 1 || n > 32) {
            return -1;
        }
        //如果是8皇后,limit该值的后8位为1,之后所有的限制就都限制在了后8位上
        int limit = (n == 32 ? -1 : (1 << n) - 1);
        //colLim表示列的限制,leftLim表示左斜线的限制,rightLim表示右斜线的限制
        //1表示已经放了皇后,0表示还没有放皇后
        return func(limit,0,0,0);
    }
    public int func(int limit,int colLim,int leftLim,int rightLim) {
        if (colLim == limit) {
            //所有的列上都放了皇后
            return 1;
        }
        int result = 0;
        //找到可以放皇后的位置(此时1的位置可以放皇后,0的位置不能放皇后)
        int pos = limit & (~(colLim | leftLim | rightLim));
        int lastOneIndex = 0;//表示pos的最右侧的1(可以放皇后的位置)
        while (pos != 0) {
            lastOneIndex = pos & (~pos + 1);
            pos -= lastOneIndex;//该位置已经被放皇后,去除
            result += func(limit,colLim | lastOneIndex,
                    (leftLim | lastOneIndex) << 1,
                    (rightLim | lastOneIndex) >>>1);
        }
        return  result;
    }
}

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

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

相关文章

Metabase学习教程:仪表盘-8

仪表板中的Markdown很有趣 如何在仪表板中使用Markdown以获得乐趣和有益。 开发有效仪表板通常包括为人们提供上下文&#xff0c;让他们了解计算是如何存在或为什么存在的。虽然精确的标题、描述和带标签的轴可以在很大程度上澄清可视化&#xff0c;但Metabase还允许您向仪表…

2022最新1w字MySQL索引面试题(附md文档)

小熊学Java个人网站&#xff1a;https://javaxiaobear.gitee.io/&#xff0c;每周持续更新干货&#xff0c;建议收藏&#xff01; 1、Mysql如何实现的索引机制&#xff1f; MySQL中索引分三类&#xff1a;B树索引、Hash索引、全文索引 2、InnoDB索引与MyISAM索引实现的区别是什…

【附源码】计算机毕业设计JAVA重工教师职称管理系统

【附源码】计算机毕业设计JAVA重工教师职称管理系统 目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; JAVA…

window像mac一样使用快捷键(AutoHotkey + SharpKeys)

自己有win和mac两台笔记本, 每天都需要在两台电脑切换进行开发, 快捷键的差异就让人很难受(个人喜好mac快捷键, 常用的几个快捷键分布比较合理), 所以网上找来了解决方案供大家参考 我想作为一名 Mac User&#xff0c; 使用 Win 首先感到不适应的应该是快捷键的差异&#xff0c…

[附源码]Python计算机毕业设计Django的项目管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

[附源码]计算机毕业设计springboot停车场管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【吴恩达机器学习笔记】八、应用机器学习的建议

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?spm1011.2415.3001.5343 &#x1f4e3;专栏定位&#xff1a;为学习吴恩达机器学习视频的同学提供的随堂笔记。 &#x1f4da;专栏简介&#xff1a;在这个专栏&#xff0c;我将整理吴恩达机器学习视频的所有内容的笔记&…

小袁博客重构V2.0版本重新发布(增加实时聊天/定时发布/权限管理/微信登录等功能)

有话说 第一代V1.0版本的博客项目&#xff0c;结构比较乱 &#xff0c;各种注入和各种校验&#xff0c;层次不分明 重构之后&#xff0c;分了七大模块 注册中心模块后台模块前台模块第三方服务模块实体类模块工具模块系统模块 降低了模块间的耦合度&#xff0c;结合Valid注…

RabbitMQ初步到精通-第十一章-RabbitMQ之常见问题汇总

目录 RabbitMQ之常见问题汇总 1.rabbitmq丢消息场景 1.1 消息未持久化丢失 1.2 消费时消息丢失 1.3 如何阻止消息丢失 2. mq消费消息是pull 还是 push 2.1 pull形式消费 2.2 push形式消费 3. mq重复消费场景 3.1 生产端重复情况 3.2 消费端重复 3.3 如何防止 4.pre…

行业新趋势!利尔达OpenCPU方案助力水表厂商破局

在“十四五”规划数字化转型的大背景下&#xff0c;水务行业的不断发展对智能水表的需求呈爆发式增长&#xff0c;NB-IOT智能水表凭借其低功耗、低成本、安全、便捷、智能的特点较好解决了传统抄表的痛点&#xff0c;迅速成为行业市场的主角。 但过去两年里&#xff0c;“缺芯…

Rust机器学习之Plotters

Rust机器学习之Plotters 本文将带领大家学习Plotters的基础用法。重点学习Plotters的图表元素和常用图表的使用。 本文是“Rust替代Python进行机器学习”系列文章的第四篇&#xff0c;其他教程请参考下面表格目录&#xff1a; Python库Rust替代方案教程numpyndarrayRust机器…

关于账本数据库:你想知道的这里都有

&#x1f495;前言&#xff1a;十二月份出个openGuass集合专栏&#xff0c;带领大家浅浅的认识一下国产数据库吧&#x1f495; 1. 什么是账本数据库 区块链大家想必都耳熟能详&#xff0c;比特币、以太坊甚至狗狗币等代币&#xff0c;作为区块链的代名词&#xff0c;不仅牵动着…

《歌在飞》在抖音播放7.7亿,歌者苏勒亚其其格用公益让爱心传递

随着短视频的流行&#xff0c;抖音平台也被大家所熟知&#xff0c;很多好听的音乐作品&#xff0c;都是通过抖音平台传唱开来。 曾经有一首《歌在飞》的音乐作品&#xff0c;在抖音平台传唱度很广&#xff0c;截止目前已经有7.7亿的播放量。据悉&#xff0c;《歌在飞》这首歌曲…

基于QPSK的载波同步和定时同步性能仿真,包括Costas环的gardner环

目录 1.算法描述 2.matlab算法仿真效果 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 载波同步是相干解调的基础&#xff0c;不管对于模拟通信还是数字通信来说&#xff0c;只要是相干解调&#xff0c;接收端都必须提供同频同相的载波。当然&#xff0c;若采用基带传输&#…

hadoop 3.x大数据集群搭建系列7-安装Hudi

文章目录编译环境准备一. 下载并解压hudi二. maven的下载和配置2.1 maven的下载和解压2.2 添加环境变量到/etc/profile中2.3 修改为阿里镜像三. 编译hudi3.1 修改pom文件3.2 修改源码兼容hadoop33.3 手动安装Kafka依赖3.4 解决spark模块依赖冲突3.4.1 修改hudi-spark-bundle的p…

pytest + yaml 框架 - 3.全局仅登录一次,在用例中自动在请求头部添加Authentication token认证

前言 我们在使用自动化测试框架的时候&#xff0c;经常会遇到一个需求&#xff0c;希望在全局用例中&#xff0c;仅登录一次&#xff0c;后续所有的用例自动带上请求头部token 或者cookies。 环境准备 Python 3.8版本 Pytest 7.2.0 最新版 pip 安装插件 pip install pytes…

[附源码]Python计算机毕业设计Django的实验填报管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;我…

OSSID: Online Self-Supervised Instance Detection by (And For) Pose Estimation

许多机器人操作算法都需要 实时目标姿态估计。然而&#xff0c;最先进的目标姿态估计方法是针对一组特定的对象进行训练的&#xff1b;因此&#xff0c;这些方法需要 重新训练 以估计每个新对象的姿势。本文提出了 OSSID 框架&#xff0c;利用 慢速零样本 姿态估计器 来 自监督…

OpenGL 图像色调

目录 一.OpenGL 图像色调 1.IOS Object-C 版本1.Windows OpenGL ES 版本2.Windows OpenGL 版本 二.OpenGL 图像色调 GLSL Shader三.猜你喜欢 零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 >> OpenGL ES 基础 零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录…

Spring | IOC技术之Bean的配置与实例化

&#x1f451; 博主简介&#xff1a;    &#x1f947; Java领域新星创作者    &#x1f947; 阿里云开发者社区专家博主、星级博主、技术博主 &#x1f91d; 交流社区&#xff1a;BoBooY&#xff08;优质编程学习笔记社区&#xff09; 文章目录Bean的基础配置1、id 与 cla…