【递归,搜索与回溯算法 综合练习】深入理解暴搜决策树:递归,搜索与回溯算法综合小专题(二)

  

 


优美的排列


    题目解析    



    算法原理    


    解法  :暴搜    


    决策树    


红色剪枝:用于剪去该节点的值在对应分支中,已经被使用的情况,可以定义一个 check[ ]


紫色剪枝:perm[i] 不能够被 i 整除,i 不能够被 perm[i] 整除,此时分支就要执行紫色剪枝


    设计函数    



    编写代码    



 N皇后


    题目解析    


本题的算法原理是比较简单的,难点在于剪枝操作和代码实现能力; 


    算法原理    


    解法:暴搜    


    决策树    


决策树的任务:给一个行数,每次枚举这一行的一个格子,枚举的格子看是否同列或者主副对角线是否有皇后,没有则在该格子放一个皇后,并停止枚举这一行剩下的格子,递归下一行; 

绿色剪枝:剪去遍历的格子所在列,出现其他皇后的情况;

紫色剪枝:剪去遍历的格子所在主副对角线,出现其他皇后的情况;

所以 N = 3,3皇后是没有合法的放置方法的 ;

当我们的行数为 N+1,说明已经枚举到了一种合法的结果;


    如何剪枝:考虑当前位置,能否放上皇后    


     策略一:无脑循环    


我们在遍历到一个格子的时候,使用四个循环判断当前格子所在行,列,左对角线,右对角线是否放有其他皇后,总体时间复杂度 O(N) = 4N * (2 ^N);虽然时间复杂度高,但是也是可以通过的

我们可以对这个方法进行优化,因为我们的决策树是每一行的其中一个格子用来放皇后,所以行是一定不会出现皇后攻击的情况的,所以只用看列,左对角线,右对角线是否放有其他皇后;


     策略二:类似哈希表的策略     


对于棋盘,我们分别定义两个 boolean 类型的数组 row[ ],col[ ] ,用于判断某一行或者某一列是否放置皇后;

 如果某个格子放置有皇后,对应的 row[ i ] ,col [ j ] 要置为 true ;后续再进行决策的时候,就可以先看看对应的 row,col 是否为 true,任意一个为 true 则不用再考虑本次枚举的格子;


接下来,我们来解决主对角线和副对角线的情况;

我们通过观察可以发现,当皇后要放置 N 个时,对应的主对角线和副对角线都是 2 * N - 1;

并且斜率分别是 1 和 -1,所以对于一条对角线,可以用y = x + b 或者 y = -x +b 来表示;

  • 对于主对角线,则有 y -  x = b ,纵坐标 + 横坐标为一个定值;
  • 对于副对角线,则有 x + y = b , 纵坐标 - 横坐标为一个定值;

所以我们再次定义两个 boolean 类型的数组 ,dig1,dig2 ,分别表示主对角线和副对角线;这两个数组的长度为 2*N ,用于存储所有的主对角线,或者副对角线;

用 b = y - x ,b = y + x 来表示某一条对角线的映射关系,当 dig1[ b ] == true || dig2 [ b ] == true,则说明该格子所在对角线放有其他皇后;


但是还有一个细节问题:

对于上图的主对角线,y - x  是一个负数,如果直接使用 dig1 [ b ] 会越界;

解决办法:添加上一个偏移量 n:y - x + n = b + n,让对角线统一向上移动 n 个单位,来处理截距为负数的情况;所以针对主对角线,我们判断的是 dig1[ b + n ] 是否是 true 即可;


    编写代码    


    前期初始化操作    



     主逻辑    



有效的数独


    题目解析    


本题并不是关于暴搜的题目,而是一个哈希表的题;我们通过讲解这道题的算法原理 ,为下一道题 解数独 做好铺垫


    算法原理    


    解法:暴搜    



 我们先来定义一个 boolean 类型的数组 row [  ] [  ]:

第一个 [ i ] 表示的是数独表中的第 i 行, 第二个 [ j ] 表示的是在这一行有没有出现 j 这个数字;

如:row [ 2 ][ 4 ] 表示的是第二行有没有出现 4 这个数字,有的话 row [ 2 ][ 4 ] == true;


col[ i ][ j ] 数组同理,表示的是第 i 列是否出现了 j 这个数字 ;


除了用数组来表示数度表外,我们也可以用哈希表来表示数独表,并且用哈希表非常巧妙:

我们是以一个3 x 3 的小数独表作为一个单位格子的,此时下标就只有 0,1,2;


我们设置一个 boolean 类型的数组 grid : 

grid [ 0 ][ 0 ] 表示左上角第一个 3x3 的大方格;


为了查看一个 3x3 的大方格所有数是否都出现过,我们再开一个空间给 grid: 


如何定义小方格和大方格下标的映射关系呢?

 当有一个元素的位置为 [ x , y ] ,映射的九宫格下标位置为 [ x/3 , y/3 ];


    编写代码    



解数独


    题目解析    



    算法原理    


    解法 : 暴搜   


    决策树    


上图代表决策树的某一条分支,我们可以发现,当按照其中一条分支填到第一行最后一个格子时,第一行每使用过的最后一个元素可能是不能填入该格子中的;


那我们怎么知道这条分支的选择不能填满数独表呢?在遍历某个 ' . ' 的格子时,如果所有数都不符合题意,我们返回 false 即可;

这个代码的报错原因,就是没有对【因为前面的选择,导致某一个格子 1 到 9 都不能填入】的情况进行处理;


所以如果遇到【某一个格子 1 到 9 都不能填入】的情况,我们就应该向上返回 false,因此,我们的 dfs 应该设置 boolean 类型的返回值,告诉上一层,这种选法是否可以得到正确的数独,如果返回 false,我们就要让上一层的格子尝试下一个数;

dfs 的参数其实可以直接把 board 数组传入即可;在 dfs 中遍历 board ,专门处理 board[ i ][ j ] == '.'  的情况;


    编写代码    


    初始化     



    填数逻辑     



    攻克难点     


本题难点就是要想到 dfs 是 boolean 类型,并且要找到 dfs 中合适的位置进行返回;


    对这三处 return 的解读    




单词搜索


    题目解析    



    算法原理    


    解法 :深度优先遍历   


    模拟过程    


我们以下面这个矩阵和 word 为例子来模拟过程: 


刚开始,会先遍历矩阵中所有的元素,直到找到word 的第一个字符 ' A '


此时会对当前 A 的格子上下左右进行扫描,直到找到 B:


对于当前位置的 A ,上下左右位置并没有 B ,说明这个 A 不是我们要找的 A ,我们寻找下一个 A:


此时,我们发现当前 A 的位置右边和下方都有 B ,就需要递归这两种情况:

下方的 B 上下左右查找,并没有找到 C,我们遍历右边的 B 


此时的情况和上面同理: 


最终得到结果,返回 true: 

如果按照上面的模拟过程,矩阵找不到 word ,则返回 false; 


    决策树    



    函数设计     



    细节问题一:如何避免走重复路径    


    问题描述     



    模拟过程    



     解决方法一: 设置一个 boolean 数组    


定义一个跟原始矩阵相同规模的 boolean 数组 :

用 visit 来标记当前位置,下次遍历到某一个位置时,通过 visit 查看这个位置是否已经被使用过;


     解决方法二: 修改原始矩阵的值     


当我们对某一个格子进行上下左右查找,查找到下一个字符时,把这个位置修改成 ' . ' 

面试的时候要问问面试官可不可以修改原始矩阵,修改原始矩阵的行为不保险;


    细节问题二:用向量数组映射  ( i , j ) 位置的上下左右坐标     


设置两个一维数组 dx[ 4 ] , dy [ 4 ] : 


dx[ i ] 和 dy [ i ] 要能映射到同一个方向,映射关系如下:

我们使用一个 for 循环,就可以一个坐标的上下左右关系全部找到;如果要找 8 个方向,我们就定义两个长度为 8 的数组,来表示 8 个不同的方向;这种方法在二维数组表示方向的时候,是非常好用的;


    编写代码    


    准备工作    


在主函数中,先遍历一次矩阵,找到第一个 word[ 0 ] ,然后调用 dfs,从第一个 word[ 0 ] 所在位置开始找 word 剩下的元素;


    主逻辑     



    代码细节详解     






 模拟上述对 return  会遇到的情况 :


黄金矿工


    题目解析    



    算法原理    


本题的算法原理和上一题是一类题型,解法大差不差,只是一些细节问题不同;这一题先尝试自己编写代码,再根据老师的视频改进;


    解法:暴搜     



    编写代码    



    编写历程    





那么,我们什么时候在主函数更新结果呢?如果要设置递归出口,就要再写一层 for 循环,判断上下左右的 vis ==true || grid == 0,对于这道题是没有必要设置递归出口的;


只需要找到一轮递归的最大值 tmp 即可,并且更新 ret 即可;所以我们一进入 dfs 就更新 ret


    总结     

关于更新结果的问题是难点:尤其是在哪里更新结果?这么更新结果有什么用?为什么要这样更新结果?


每次作出一题,都要想清楚这几个问题,并且学会新的处理细节问题的方式,如:

  • 二维矩阵搜索路径时,避免走重复路径的方法;
  • 使用向量坐标表示一个格子不同的方向;

不同路径Ⅲ


    题目解析    




    算法原理    


    解法 :暴搜   



    编写代码    



    优化    


减少循环次数: 


    继续优化    


我们可以对递归出口进行优化,原来是只有合法路径才 return ,现在是只要走到终点就 return: 


总结 


关于暴搜的题目,算法原理其实并不难,重点考察的就是我们的代码能力,以及能否发现细节问题,并且对细节问题进行合理的处理; 


 

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

观察者模式(sigslot in C++)

大家,我是东风,今天抽点时间整理一下我很久前关注的一个不错的库,可以支持我们在使用标准C的时候使用信号槽机制进行观察者模式设计,sigslot 官网: http://sigslot.sourceforge.net/ 本文较为详尽探讨了一种观察者模…

GitCode 光引计划投稿|智能制造一体化低代码平台 Skyeye云

随着智能制造行业的快速发展,企业对全面、高效的管理解决方案的需求日益迫切。然而,传统的开发模式往往依赖于特定的硬件平台,且开发过程繁琐、成本高。为了打破这一瓶颈,Skyeye云应运而生,它采用先进的低代码开发模式…

高校就业管理:系统设计与实现的全流程分析

3.1可行性分析 在项目进行开发之前,必须要有可行性分析报告,分别从技术角度,经济角度,操作角度上面进行分析,经过可行性分析是实现科学开发的必要步骤。 3.1.1技术可行性 从技术的角度出发,目前采用开发的技…

超级AI图像放大工具Upscayl:让你的照片细节更清晰,色彩更鲜艳!

前言 Hello大家好,我又来推荐非常好用的AI图片无损放大器,模糊图片秒变高清,Upscayl是一个免费开源的AI图像超分辨率工具。它使用AI模型来通过猜测细节的方式增强图像并提高其分辨率。该工具适用于Linux、macOS和Windows操作系统 安装环境 [名称]&…

1.gitlab 服务器搭建流程

前提条件: 一、服务器硬件水平 搭建gitlab服务器最低配置要求2核4G,低于这个配置的服务器运行效果很差。 gitlab官网:https://about.gitlab.com/ 下载地址:gitlab/gitlab-ce - Packages packages.gitlab.com 本机ubuntu 二、安装依赖 su…

Ai编程从零开始全栈开发一个后台管理系统之用户登录、权限控制、用户管理-前端部分(十二)

云风网 云风笔记 云风知识库 一、创建前端部分 1、vite初始化项目 npm create vitelatest admin-frontend – --template vue-ts 2、安装必要的依赖 npm install vue-router pinia axios element-plus element-plus/icons-vue安装完成后package.json如下: {&qu…

CVE-2024-34351 漏洞复现

CVE-2024-34351&#xff0c;由Next.js异步函数createRedirectRenderResult导致的SSRF。 影响版本&#xff1a;13.4.0< Next.js < 14.1.1 参考文章&#xff1a; Next.js Server-Side Request Forgery in Server Actions CVE-2024-34351 GitHub Advisory Database Gi…

怎么理解GKE Role-Based Access Control (RBAC) 和 Pod Security Policies (PSP)

怎么理解GKE Role-Based Access Control (RBAC) 和 Pod Security Policies (PSP) 理解 Google Kubernetes Engine (GKE) 中的角色基于访问控制&#xff08;RBAC&#xff09;和 Pod 安全策略&#xff08;PSP&#xff09;对于确保集群安全性至关重要。以下是对这两个概念的详细解…

什么是 DevOps 自动化?

DevOps 自动化是一种现代软件开发方法&#xff0c;它使用工具和流程来自动化任务并简化工作流程。它将开发人员、IT 运营和安全团队聚集在一起&#xff0c;帮助他们有效协作并交付可靠的软件。借助 DevOps 自动化&#xff0c;组织能够处理重复性任务、优化流程并更快地将应用程…

帝国CMS:如何去掉帝国CMS登录界面的认证码登录

如果在安装的时候&#xff0c;不小心选中了认证码选项&#xff0c;那么后面登录帝国后台都会要求输入认证码才能登录&#xff0c;如何去除这个设置呢&#xff0c;笔者以古诗词网 www.gushichi.com为例&#xff0c;为大家举例说明&#xff01; 去除步骤如下&#xff1a; 1.前往…

4.2V单节锂电池充电电路(TP4056)、USB与锂电池切换电路分享

一、充电原理图 1、连接说明 BAT_VCC和BAT_GND连接电池 VUSB和GND连接USB电源 2、芯片介绍 a、DW01 DW01芯片是一种电池管理保护芯片&#xff0c;主要用于锂离子电池的保护和管理。DW01芯片具有以下特点&#xff1a; 电池电压保护&#xff1a;DW01芯片可以监测和保护电池的…

ChatGPT生成接口文档实践案例(二)

不难发现&#xff0c;两个方案都出色地完成了接口文档的生成&#xff0c;但笔者更喜欢Response 2的表达&#xff0c;因为其描述更加全面。 还可以让ChatGPT生成符合OpenAPI 3.0规范的接口文档&#xff0c;以便于项目相关成员阅读&#xff0c;如图5-13所示。 为什么要生成OpenAP…

MFC用List Control 和Picture控件实现界面切换效果

添加List Control 和Picture控件 添加 3个子窗体 把子窗体边框设置为None, 样式设为Child 声明 CListCtrl m_listPageForm;void ShowForm(int nIndex);void CreatFormList();void CMFCApplication3Dlg::DoDataExchange(CDataExchange* pDX) {CDialogEx::DoDataExchange(pDX);DD…

JavaWeb Servlet的反射优化、Dispatcher优化、视图(重定向)优化、方法参数值获取优化

目录 1. 背景2. 实现2.1 pom.xml2.2 FruitController.java2.3 DispatcherServlet.java2.4 applicationContext.xml 3. 测试 1. 背景 前面我们做了Servlet的一个案例。但是存在很多问题&#xff0c;现在我们要做优化&#xff0c;优化的步骤如下&#xff1a; 每个Fruit请求都需…

frp内网穿透云服务器。云服务器映射多个家庭局域网内网端口。家庭Windows主机内网运行多个web程序

这篇文章最终要实现的效果是&#xff0c;把云服务器的公网IP绑定到自己本地局域网上的主机一样的效果。相当于局域网主机有了一个自己的公网IP地址。 FRP (Fast Reverse Proxy) 是一个用 Go 语言编写的高性能反向代理应用程序&#xff0c;主要用于内网穿透。它允许位于 NAT 或…

windos 安装docker

文章目录 安装1.下载安装包2.双击安装软件 验证修改国内镜像地址FAQDocker Engine stopped 小结 安装 1.下载安装包 到官网下载适配的安装包&#xff1a;https://www.docker.com/products/docker-desktop/ 2.双击安装软件 选择ok 等待安装依赖 安装完成以后会重启电脑&am…

【已解决】黑马点评项目Redis版本替换过程中误删数据库后前端显示出现的问题

为了实现基于Redis的Stream结构作为消息队列&#xff0c;实现异步秒杀下单的功能&#xff0c;换Redis版本 Redis版本太旧了&#xff0c;所以从3.2.1换成了5.0.14 此时犯了一个大忌&#xff0c;因为新的Redis打开后&#xff0c;没有缓存&#xff0c;不知道出了什么问题&#xf…

Odoo 免费开源 ERP:通过 JavaScript 创建对话框窗口的技术实践分享

作者 | 老杨 出品 | 上海开源智造软件有限公司&#xff08;OSCG&#xff09; 概述 在本文中&#xff0c;我们将深入研讨如何于 Odoo 18 中构建 JavaScript&#xff08;JS&#xff09;对话框或弹出窗口。对话框乃是展现重要讯息、确认用户操作以及警示用户留意警告或错误的行…

Tool之Excalidraw:Excalidraw(开源的虚拟手绘风格白板)的简介、安装和使用方法、艾米莉应用之详细攻略

Tool之Excalidraw&#xff1a;Excalidraw(开源的虚拟手绘风格白板)的简介、安装和使用方法、艾米莉应用之详细攻略 目录 Excalidraw 简介 1、Excalidraw 的主要特点&#xff1a; Excalidraw 安装和使用方法 1、Excalidraw的安装 T1、使用 npm 安装&#xff1a; T2、使用 …

探索CSDN博客数据:使用Python爬虫技术

探索CSDN博客数据&#xff1a;使用Python爬虫技术 在数字化的浪潮中&#xff0c;数据的获取与分析变得日益关键。CSDN作为中国领先的IT社区和服务平台&#xff0c;汇聚了海量的技术博客与文章&#xff0c;成为一座蕴藏丰富的数据宝库。本文将引领您穿梭于Python的requests和py…