【递归,搜索与回溯算法 & floodfill 算法】深入理解 floodfill 算法:floodfill 算法小专题

【递归,搜索与回溯算法 & floodfill 算法】深入理解 floodfill 算法:floodfill 算法小专题

   

  


图像渲染


    题目解析    



    算法原理    


    解法:暴搜    


     模拟过程     



    递归过程:  



     回溯过程:  



    处理细节问题    


但是如果在上述矩阵的情况下,给我们的 color 不是 2 ,而是 1,也就是原始像素值和要修改像素值相同的情况,此时很有可能在递归的时候走重复路径:

我们不处理好这种特殊的情况,就很容易会写出 bug;所以在编写代码的时候,我们先判断一下,if (image[sr][sc]==color),直接返回即可,因为无需修改; 


    编写代码    


 报错原因:没有修改 image[ sr ][ sc ] 为 color



优化:本题并不需要 vis 数组来标记走过的格子,因为走过的格子都会修改,修改后会被剪枝条件筛查掉,并且这道题也没有递归出口,也不需要恢复现场;


岛屿数量


    题目解析    




    算法原理    


    解法:暴搜    



    处理细节问题     


 为了避免走重复路径,我们定义一个 vis ,用来标记已经走过的小方格 :


    编写代码    



报错原因:

剪枝条件 grid[ x ][ y ] == ' 1 ' ,而不是 grid[ x ][ y ] ==  1;

ret++ 设置的位置不对,是统计完一块岛屿的时候,ret 才+1,而上面这样设置,是在一块陆地(一个小格子)上下左右都查找完之后 +1,而不是找到一个完整的岛屿,ret 才+1;

在下图 ret++ 设置的位置,表示以 grid[ i ][ j ] 这块陆地开始递归,向外查找别的陆地,直到找完整块联通的陆地,递归才会结束;

递归结束,表明已经找到了以 grid[ i ][ j ] 这块陆地为起点所形成的一个完整的岛屿,ret++;


    fillflood 部分     


    思考 :做了那么多题目,为什么有的题目需要恢复现场,有的题目不需要恢复现场呢?   

恢复现场是因为决策树衍生出的多条分支,为了保证每条分支的结果,不被同层的其他已经递归过的分支影响,回溯时,就要把其他分支修改的 path 还原;

而这道题不用恢复现场,原因是因为大多数 fullfill 算法类型的题,是要找出一块矩阵所有的联通区,这些联通区需要被记录,因为这些联通区都会参与最终结果,且各个联通区不会出现重叠,所以在回溯时不需要也不能把记录过的联通区还原;

岛屿的最大面积


    题目解析    



    算法原理    



    解法:暴搜    



     编写代码    



报错原因:count 设置为  dfs 的一个参数,无法记录整个岛屿的面积,会出现只记录一部分,回溯时把记录部分恢复的情况; 



被围绕的区域


    题目解析    


难点:如果联通的 O 区域中,只要有一块能在矩阵的边上,那么这一整块联通区 O 都不能被 X 包围,而这道题的难点就是处理这种情况;


    算法原理    


    解法一:直接使用 floodfill 算法进行深度优先遍历   


我们对一个联通区进行深度优先遍历,直到修改完联通区所有的 O ,但是如果遇到一块非法 O,我们就向上回溯,并且把修改成 X 的 O 全部恢复;

这个思路是可以的,但是代码会非常难写,因为被包围的联通区,和未被包围的联通区深度优先遍历的处理方法是不同的,按照这个思路,我们就需要写两份 dfs ;

并且还有一个更致命的问题,就是我们在进行深度优先遍历时,是先搜索,才能对一块小方块的合法与否进行判断,那么在判断之前,我们并不知道应该调用哪一份 dfs ;


    解法二:正难则反    


如果直接上手写代码比较难的话,我们可以采用正难则反的方法;

处理与边界相连的区域不好上手;那么我们就可以先处理矩阵的最外围,当最外围出现 O,就把O所在的联通区标记一下,此时剩下的 O ,就是我们应该处理的; 


所以,我们可以在真正处理矩阵联通区之前,先扫描矩阵的四条边,如果四条边上扫描到 O, 我们就对这个 O 进行深度优先遍历,标记遍历到的联通区,剩下的联通区就是我们要处理的;


    处理细节问题    


这道题的标记方法,修改原始矩阵会比设置 vis 数组更好,因为这道题本来就是要修改原始矩阵:


    编写代码    


    大体框架    



    fillflood 部分     



    总结    

本题,我们又学会了正难则反的思想,以及如何遍历矩阵的四条边; 

太平洋大西洋水流问题


    题目解析    


在看这道题之前,我们先来看看题目讨论: 


 这道题上面的题目的文字我们可以不看,煮啵会用示例一,来讲清楚这道题要我们做什么;




    算法原理    


    解法一:枚举所有点并且直接判断     


我们可以暴力枚举所有的点,如果一个点可以流向大西洋和太平洋,我们就把这个点的坐标存到最终的 ret 中 ;


如果直接判断,代码虽然不难写,但是会判断很多重复的路径:

 比如图中这个 4,如果想去太平洋,可以通过暴搜,找到所有流向中,其中能流向太平洋的一条路径:


然后我们再来枚举高度为 5 的小格子,就有可能会判断到重复的路径:

枚举小方格使用直接判断的方法,是会判断多次重复路径的,如果这个矩阵的范围非常大,那么无效的时间开销也会变得非常大 ;


    解法二:正难则反   



我们最终要找的是某个点能不能流向太平洋,那我们就反过来看,我们可以假设太平洋的水逆着流,会流向哪些位置(水从海拔低的格子逆着流向海拔高或者等海拔的格子) 


为了降低时间复杂度,遍历过的格子,就不用重新遍历: 


而能流向大西洋的格子同理,让大西洋的水逆向流:


此时,重复的格子就是我们最终的返回值 ,这些重复格子既可以流向太平洋,也可以流向大西洋:


    处理细节问题     



    编写代码    


    大框架    



    fillflood 部分    



par ,atl 作为 dfs 的参数,把 par ,atl 设置成全局变量也可以,设置成局部变量也可以,都能起到记录的结果不会被自动恢复作用;


扫雷游戏


    题目解析    




    算法原理    


算法原理就是扫雷游戏的规则,我们可以自己去玩两把感受一下; 


    解法:模拟 + fillflood 深搜     


我们以示例一来讲解扫雷游戏的步骤: 


 对于扫雷游戏:



    处理细节问题    


本题是八联通,需要扩展向量数组:


    编写代码    


    准备工作    



    核心代码    



机器人的运动范围


    题目解析    




    原题    

地上有一个m行n列的方格,从坐标 [0,0]到坐标[m-1,n-1]。机器人从坐标[0,0]的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格[35,37],因为3+5+3+7=18。但它不能进入方格[35,38],因为3+5+3+8=19。请问该机器人能够到达多少个格子? 

    算法原理    


    解法:深度优先遍历   


 通过一次深度优先遍历,找到满足:  digit(i) + digit(j) <= cnt 性质的格子即可,本题的算法原理很简单,考验的是我们的代码能力;


    编写代码    



报错原因:不定义标记数组,ret 会统计重复走过的格子和递归回溯经过的格子的总数:


     准备工作    



    核心代码    



   

Read more

GitHub Student Developer Pack申请攻略:无校园邮箱的替代认证方案

1. 没有校园邮箱,还能申请GitHub学生包吗? 当然可以,而且我告诉你,这可能是很多国内学生开发者最关心的问题。我刚开始接触编程的时候,也以为那个金光闪闪的GitHub Student Developer Pack必须得有带.edu后缀的邮箱才能申请,差点就放弃了。后来帮好几个学弟学妹成功搞定,才发现官方其实留了“后门”,或者说,提供了更灵活的认证思路。这个学生包的价值,远不止是省点钱,它更像是一张进入开发者世界的VIP门票,里面集成了几十个顶级开发工具的免费套餐,比如GitHub Copilot的免费使用、DigitalOcean的云服务器额度、Namecheap的域名、各种IDE的专业版,对于学生党来说,能省下大几千的开销,更重要的是能无障碍地用上生产级的工具链。 但现实情况是,很多国内高校并不为学生提供官方的校园邮箱,或者提供的邮箱格式并非国际通用的.edu域名。还有些同学可能是非全日制、远程教育,或者已经毕业但仍在深造,手头根本没有符合条件的邮箱。难道就因为一个邮箱,就要错过这么多资源吗?当然不。GitHub官方的学生认证,核心是验证你的“学生身份”,而不是“邮箱后缀”

By Ne0inhk
linux启程指南——体悟虚拟开源天地的漫步翩翩

linux启程指南——体悟虚拟开源天地的漫步翩翩

文章目录 * 前言 * 一、何为Linux? * 二、Linux的组成与运作 * 三、具体安装指南 * 3.1 云服务器的安装 * 3.2 xshell安装 * 3.3 云服务器配置 * 3.4创建普通用户 * 3.5 删掉普通用户 * 四、Linux的哲学与精神 * 五、Linux的多样性与发展 * 六、为什么选择Linux? * 结语:从这片草原开始 前言 每个人的心中都有一片理想的草原,那是自由的象征,是属于自己的一片净土。而在我眼中,Linux便是那片草原,它不拘一格,广阔无垠,似乎能容纳所有热爱自由与探索的人。它既不像风格华丽的城市操作系统那般繁复,也不像急功近利的商业软件那样设限。Linux,如同晨曦中的一缕清风,带着一种原始的纯粹与不羁。 本篇将从linux的背景出发,详细给出linux的安装指南,助力大家开启linux启程之旅。 一、何为Linux? Linux,

By Ne0inhk

从零开始:学生与教育工作者如何免费解锁GitHub Copilot的全套能力

学生与教育工作者如何零成本解锁GitHub Copilot的完整指南 1. 教育认证:开启免费Copilot之旅的关键步骤 对于在校学生和教师而言,GitHub提供了一条专属的绿色通道。通过教育认证,你可以完全免费获得Copilot的专业级代码辅助功能,无需经历60天试用期的繁琐流程。这个认证过程虽然需要一些耐心,但绝对值得投入时间。 教育认证的核心在于验证你的学术身份真实性。GitHub会要求你提供以下材料之一: * 学生身份验证:有效的学生证、在学证明或学信网认证报告 * 教师身份验证:教师资格证、工作证或学校官方邮箱 重要提示:使用学校邮箱(.edu或学校专属域名)能大幅提升认证通过率。如果材料非英文,建议附上简单翻译说明。 认证流程中的常见陷阱包括: 1. 上传的证件照片模糊不清 2. 证件有效期信息缺失 3. 使用非官方邮箱提交申请 4. 网络IP地址与学校地理位置不符 我曾帮助三位同学完成认证,发现下午3-5点(美国西部时间)提交的申请通常能在24小时内获得回复,这可能与GitHub审核团队的工作时段有关。 2. PyCharm环境下的Co

By Ne0inhk

Vscode中配置Claude code的git bash链接问题

解决VS Code中Claude Code的Git Bash链接问题 问题描述 在VS Code中使用Claude Code时出现错误提示: Error: Claude Code on Windows requires git-bash (https://git-scm.com/downloads/win). 确定git已经安装成果,且按照官方建议设置环境变量CLAUDE_CODE_GIT_BASH_PATH仍无效。 解决方案 删除特定环境变量 在Windows环境变量的用户变量部分,检查并删除CLAUDE_CODE_GIT_BASH_PATH变量(如果存在)。 将Git CMD添加到PATH 编辑用户变量中的Path,添加Git的cmd文件夹路径: * 用户级安装路径:%USERPROFILE%\AppData\Local\Programs\Git\cmd * 全局安装路径:C:\Program Files\

By Ne0inhk