当前位置: 首页 > news >正文

leetcode算法题之N皇后

N皇后也是一道很经典的问题,问题如下:

题目地址

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

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

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

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

解法:回溯

回溯是基于 DFS 的一种算法,它通过在解空间树中深度探索并尝试所有可能的解来解决问题。当发现当前路径无法满足问题的约束条件时,算法会“回溯”到上一步,尝试另一条路径

首先我们先建立一个二维数组,方便我们在回溯时直接更改对应的状态

const dp = new Array(n).fill(0).map(() => new Array(n).fill("."));

由当前问题我们可得知棋盘的每行必定要放置一个皇后,不然不会有满足题目的解,所以可以把每一列当作一层,把皇后放置后再到下一层继续放置,基本代码如下

const backtrack = (line) => {// 遍历每一行,放置皇后for (let i = 0; i < n; i++) {dp[line][i] = "Q";backtrack(line + 1)// 回溯的核心,当我们使用完后一定要将状态恢复,不然会影响下一个结果dp[line][i] = ".";}
}backtrack(0);

接下来的问题就是我们要怎么判断当前位置可不可以放置皇后,有的童鞋可能想着所有方向都遍历一下,其实不用这么麻烦,因为我们是由上往下放置,所以只需要判断左上,上,右上的方向就可以啦

// 检测位置是否可以放皇后
const checkPosition = (x, y) => {// 检测上方let tx = x;while (--tx > -1) {if (dp[tx][y] === "Q") {return false;}}// 检测上斜左let lx = x,ly = y;while (--lx > -1 && --ly > -1) {if (dp[lx][ly] === "Q") {return false;}}// 检测上斜右let rx = x,ry = y;while (--rx > -1 && ++ry < n) {if (dp[rx][ry] === "Q") {return false;}}return true;
};

既然说到回溯,那肯定涉及到剪枝问题了,其实也不用做啥,当我们发现某一行无法放置任何皇后时,我们什么都不做,直接回溯到上一行即可

完整代码如下:

/*** @param {number} n* @return {string[][]}*/
var solveNQueens = function (n) {let dp = new Array(n).fill(0).map(() => new Array(n).fill("."));const result = [];let queenNum = n;// 检测位置是否可以放皇后const checkPosition = (x, y) => {// 检测上方let tx = x;while (--tx > -1) {if (dp[tx][y] === "Q") {return false;}}// 检测上斜左let lx = x,ly = y;while (--lx > -1 && --ly > -1) {if (dp[lx][ly] === "Q") {return false;}}// 检测上斜右let rx = x,ry = y;while (--rx > -1 && ++ry < n) {if (dp[rx][ry] === "Q") {return false;}}return true;};const pushResult = () => {let newDp = [];for (let i = 0; i < n; i++) {newDp[i] = dp[i].join("");}result.push(newDp);};const backtrack = (line) => {if (line === n) {pushResult();return;}for (let i = 0; i < n; i++) {// 判断是否可以放置皇后if (line === 0 || (line > 0 && checkPosition(line, i))) {dp[line][i] = "Q";backtrack(line + 1);dp[line][i] = ".";}}};backtrack(0);return result;
};

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 软件测试要学习的基础知识——黑盒测试
  • 静态路由与默认路由和实验以及ARP工作原理
  • 动画展示梯度下降(二维)
  • XSS的DOM破坏
  • Linux·权限与工具-yum与vim
  • 说一下Android中的IdleHandler
  • 每日一问:Kafka消息丢失与堆积问题分析与解决方案
  • MFC在OPENGL循环绘制中添加进度条控件后运行速度变慢
  • 设计模式 - 装饰器模式
  • 在IntelliJ IDEA中使用Git推送项目
  • [手机Linux PostmarketOS]五, docker安装和使用
  • Unity如何使用Spine动画导出的动画
  • webrtc学习笔记3
  • HTTP的认证方式
  • C# 使用泛型协变性
  • 实现windows 窗体的自己画,网上摘抄的,学习了
  • [原]深入对比数据科学工具箱:Python和R 非结构化数据的结构化
  • 08.Android之View事件问题
  • 10个确保微服务与容器安全的最佳实践
  • codis proxy处理流程
  • iOS仿今日头条、壁纸应用、筛选分类、三方微博、颜色填充等源码
  • Iterator 和 for...of 循环
  • Java反射-动态类加载和重新加载
  • JAVA之继承和多态
  • jdbc就是这么简单
  • Lucene解析 - 基本概念
  • node和express搭建代理服务器(源码)
  • swift基础之_对象 实例方法 对象方法。
  • 互联网大裁员:Java程序员失工作,焉知不能进ali?
  • 机器学习 vs. 深度学习
  • 前端技术周刊 2019-01-14:客户端存储
  • 十年未变!安全,谁之责?(下)
  • 试着探索高并发下的系统架构面貌
  • 通过获取异步加载JS文件进度实现一个canvas环形loading图
  • 吴恩达Deep Learning课程练习题参考答案——R语言版
  • 自定义函数
  • Unity3D - 异步加载游戏场景与异步加载游戏资源进度条 ...
  • 长三角G60科创走廊智能驾驶产业联盟揭牌成立,近80家企业助力智能驾驶行业发展 ...
  • 昨天1024程序员节,我故意写了个死循环~
  • #android不同版本废弃api,新api。
  • (2)(2.10) LTM telemetry
  • (2020)Java后端开发----(面试题和笔试题)
  • (Charles)如何抓取手机http的报文
  • (Java岗)秋招打卡!一本学历拿下美团、阿里、快手、米哈游offer
  • (博弈 sg入门)kiki's game -- hdu -- 2147
  • (二)基于wpr_simulation 的Ros机器人运动控制,gazebo仿真
  • (二十六)Java 数据结构
  • (分布式缓存)Redis持久化
  • (附源码)springboot美食分享系统 毕业设计 612231
  • (九)One-Wire总线-DS18B20
  • (力扣记录)235. 二叉搜索树的最近公共祖先
  • (十一)c52学习之旅-动态数码管
  • (四)docker:为mysql和java jar运行环境创建同一网络,容器互联
  • (四)js前端开发中设计模式之工厂方法模式
  • (一)RocketMQ初步认识