Kotlin程序员面试算法宝典【2.5】
4.21 如何求解迷宫问题【出自 YMX 笔试题】难度系数★★★★☆ 题目描述被考察系数★★★★☆给定一个大小为 N×N 的迷宫一只老鼠需要从迷宫的左上角对应矩阵的[0][0]走到迷宫的右下角对应矩阵的[N-1][N-1]老鼠只能向两个方向移动向右或向下。在迷宫中 0 表示没有路是死胡同 1 表示有路。例如给定下面的迷宫图中标粗的路径就是一条合理的路径。请给出算法来找到这样一条合理路径。分析与解答最容易想到的方法就是尝试所有可能的路径找出可达的一条路。显然这种方法效率非常低这里重点介绍一种效率更高的回溯法。主要思路为当碰到死胡同的时候回溯到前一步然后从前一步出发继续寻找可达的路径。算法的主要框架如下申请一个结果矩阵来标记移动的路径if 到达了目的地打印解决方案矩阵else 1在结果矩阵中标记当前为 1 1 表示移动的路径。 2向右前进一步然后递归地检查走完这一步后判断是否存在到终点的可达的路线。 3如果步骤 2中的移动方法导致没有通往终点的路径那么选择向下移动一步然后检查使用这种移动方法后是否存在到终点的可达的路线。 4如果上面的移动方法都会导致没有可达的路径那么标记当前单元格在结果矩阵中为 0返回 false并回溯到前一步中。根据以上框架很容易进行代码实现。示例代码如下class Maze { val N 4 /* 打印从起点到终点的路线 */ fun printSolutionsol ArrayIntArray { for i in 0 until N { for j in 0 until N printsol[i][j].toString println } } /* 判断 x 和 y 是否是一个合理的单元 */ private fun isSafemaze ArrayIntArray x Int y Int Boolean { return x in 0..N - 1 y 0 y N maze[x][y] 1 } /* * 使用回溯的方法找到一条从左上角到右下角的路径 * maze 表示迷宫 x、 y 表示起点 sol 存储结果 */ fun getPathmaze ArrayIntArray x Int y Int sol ArrayIntArray Boolean { /* 到达目的地 */ if x N - 1 y N - 1 { sol[x][y] 1 return true } /* 判断 maze[x][y]是否是一个可走的单元 */ if isSafemaze x y { /* 标记当前单元为 1 */ sol[x][y] 1 /* 向右走一步 */ if getPathmaze x 1 y sol return true /* 向下走一步 */ if getPathmaze x y 1 sol return true /* 标记当前单元为 0 用来表示这条路不可行然后回溯 */ sol[x][y] 0 return false } return false } } fun mainargs ArrayString { val rat Maze val maze arrayOfintArrayOf1 0 0 0 intArrayOf1 1 0 1 intArrayOf0 1 0 0 intArrayOf1 1 1 1 val sol arrayOfintArrayOf0 0 0 0 intArrayOf0 0 0 0 intArrayOf0 0 0 0 intArrayOf0 0 0 0 if rat.getPathmaze 0 0 sol { print不存在可达的路径 } else { rat.printSolutionsol } } 程序的运行结果如下 1 0 0 0 1 1 0 0 0 1 0 0 0 1 1 14.22 如何从三个有序数组中找出它们的公共元素【出自 YMX 笔试题】难度系数★★★★☆ 被考察系数★★★☆☆题目描述给定以非递减顺序排序的三个数组找出这三个数组中的所有公共元素。例如给出下面三个数组 ar1[] {2 5 12 20 45 85} ar2[] {16 19 20 85 200} ar3[] {3 4 15 20 39 72 85 190} 。那么这三个数组的公共元素为 {20 85}。分析与解答最容易想到的方法是首先找出两个数组的交集然后再把这个交集存储在一个临时数组中最后再找出这个临时数组与第三个数组的交集。这种方法的时间复杂度为 ON1 N2 N3其中 N1、 N2 和 N3 分别为三个数组的大小。这种方法不仅需要额外的存储空间而且还需要额外的两次循环遍历。下面介绍另外一种只需要一次循环遍历、而且不需要额外存储空间的方法主要思路如下假设当前遍历的三个数组的元素分别为 ar1[i]、 ar2[j]和 ar3[k]则存在以下几种可能性 1如果 ar1[i]、 ar2[j]和 ar3[k]相等则说明当前遍历的元素是三个数组的公有元素可以直接打印出来然后通过执行 i j k使三个数组同时向后移动此时继续遍历各数组后面的元素。 2如果 ar1[i]ar2[j]则执行 i来继续遍历 ar1 中后面的元素因为 ar1[i]不可能是三个数组公有的元素。 3如果 ar2[j]ar3[k]同理可以通过 j来继续遍历 ar2 后面的元素。 4如果前面的条件都不满足说明 ar1[i]ar2[j]而且 ar2[j]ar3[k]此时可以通过 k来继续遍历 ar3 后面的元素。实现代码如下fun findCommonar1 IntArray ar2 IntArray ar3 IntArray { var i 0 var j 0 var k 0 val n1 ar1.size val n2 ar2.size val n3 ar3.size /* 遍历三个数组 */ while i n1 j n2 k n3 { /* 找到了公有的元素 */ if ar1[i] ar2[j] ar2[j] ar3[k] { print${ar1[i]} i j k } else if ar1[i] ar2[j] i else if ar2[j] ar3[k] j else k/* ar3[k]不可能是共有的元素 *//* ar2[j]不可能是共有的元素 *//* ar[i]不可能是 共有的元素 */ } } fun mainargs ArrayString { val ar1 intArrayOf2 5 12 20 45 85 val ar2 intArrayOf16 19 20 85 200 val ar3 intArrayOf3 4 15 20 39 72 85 190 findCommonar1 ar2 ar3 } 程序的运行结果如下 20 85算法性能分析这种方法的时间复杂度为 ON1 N2 N3。4.23 如何求两个有序集合的交集【出自 WY 笔试题】难度系数★★★★☆ 题目描述被考察系数★★★★☆有两个有序的集合集合中的每个元素都是一段范围求其交集例如集合{[48][913]}和{[612]}的交集为{[68][912]}。分析与解答方法一蛮力法最简单的方法就是遍历两个集合针对集合中的每个元素判断是否有交集如果有则求出它们的交集实现代码如下data class MySetvar min Int var max Int private fun getIntersections1 MySet s2 MySet MySet { return when { s1.min s2.min -when { s1.max s2.min -null s1.max s2.max - MySets2.min s1.max else - MySets2.min s2.max } s1.min s2.max -when { s1.max s2.max - MySets1.min s1.max else - MySets1.min s2.max } else -null } } fun getIntersectionl1 ArrayListMySet l2 ArrayListMySet ArrayListMySet { val result ArrayListMySet for i in l1.indices for j in l2.indices { val s getIntersectionl1[i] l2[j] if s null result.adds } return result } fun mainargs ArrayString { val l1 ArrayListMySet val l2 ArrayListMySet l1.addMySet4 8 l1.addMySet9 13 l2.addMySet6 12 val result getIntersectionl1 l2 for i in result.indices println[${result[i].min} ${result[i].max}] } 代码运行结果如下 [68] [912]算法性能分析这种方法的时间复杂度为 On^2。方法二特征法上述这种方法显然没有用到集合有序的特点因此它不是最佳的方法。假设两个集合为 s1 和 s2。当前比较的集合为 s1[i]和 s2[j]其中 i 与 j 分别表示的是集合 s1 与 s2 的下标。可以分为如下几种情况1 s1 集合的下界小于 s2 的上界 S1[i] _________S2[j] _________在这种情况下 s1[i]和 s2[j]显然没有交集那么接下来只有 s1[i1]与 s2[j]才有可能会有交集。2 s1 的上界介于 s2 的下界与上界之间S1[i] _________ S2[j] _________在这种情况下 s1[i]和 s2[j]有交集 s2[j]的下界和 s1[i]的上界那么接下来只有 s1[i1]与 s2[j]才有可能会有交集。3 s1 包含 s2S1[i] ___________________ S2[j] _________在这种情况下 s1[i]和 s2[j]有交集交集为 s2[j]那么接下来只有 s1[i]与 s2[j1]才有可能会有交集。4 s2 包含 s1S1[i] _________ S2[j] ______________在这种情况下 s1[i]和 s2[j]有交集交集为 s1[i]那么接下来只有 s1[i1]与 s2[j]才有可能会有交集。5 s1 的下界介于 s2 的下界与上界之间S1[i] _______________ S2[j] _____________在这种情况下 s1[i]和 s2[j]有交集交集为 s1[i]的下界和 s2[j]的上界那么接下来只有s1[i]与 s2[j1]才有可能会有交集。6 s2 的上界小于 s1 的下界 S1[i] _______ S2[j] _________在这种情况下 s1[i]和 s2[j]显然没有交集那么接下来只有 s1[i]与 s2[j1]才有可能会有交集。根据以上分析给出实现代码如下fun getIntersectionl1 ListMySet l2 ListMySet ListMySet { val result mutableListOfMySet var i 0 var j 0 while i l1.size j l2.size { val s1 l1[i] val s2 l2[j] if s1.min s2.min { when { s1.max s2.min - i s1.max s2.max - { result.addMySets2.min s1.max i } else - { result.addMySets2.min s2.max j } } } else if s1.min s2.max { if s1.max s2.max { result.addMySets1.min s1.max i } else { result.addMySets1.min s2.max j } } else { j } } return result } fun mainargs ArrayString { val l1 mutableListOfMySet val l2 mutableListOfMySet l1.addMySet4 8 l1.addMySet9 13 l2.addMySet6 12 val result getIntersectionl1 l2 for i in result.indices println[${result[i].min} ${result[i].max}] }算法性能分析这种方法的时间复杂度为 On1n2其中 n1、 n2 分别为两个集合的大小。

相关新闻

不聊房子、不卷票子,「全民健康热」带火了阿福

不聊房子、不卷票子,「全民健康热」带火了阿福

作者:高藤原创:深眸财经(chutou0325)今年春节回家,我发现年夜饭桌上的话题变了。以往围炉夜话,中心议题绕不开“升职加薪”“买房买车”和“催婚催生”,长辈们关心的,是你的年终奖几…

2026/7/4 10:13:56 阅读更多 →
【SLAM】为什么像orb slam,vins等视觉SLAM开源算法里,精度上双目常常低于单目?

【SLAM】为什么像orb slam,vins等视觉SLAM开源算法里,精度上双目常常低于单目?

知乎:为什么像orb slam,vins等视觉SLAM开源算法里,精度上双目常常低于单目? 深层次原因(不是“单目更强”,而是“双目收益没被吃满”) 1) 双目“理论优势”成立的前提很苛刻 双目确实能直接给…

2026/5/17 6:50:33 阅读更多 →
《计算机视觉:从入门到精通》技术手册 第18章 人体姿态估计与动作捕捉

《计算机视觉:从入门到精通》技术手册 第18章 人体姿态估计与动作捕捉

目录 第18章 人体姿态估计与动作捕捉 18.1 2D姿态估计 18.1.1 热图回归与坐标回归方法 18.1.2 堆叠沙漏网络(Stacked Hourglass) 18.1.3 高分辨率网络(HRNet)与多尺度融合 18.1.4 自底向上方法:OpenPose, PifPaf, DEKR 18.2 3D姿态估计与重建 18.2.1 单目3D姿态估…

2026/7/3 22:07:04 阅读更多 →

最新新闻

Startup AI自动化落地实战:客服、库存与决策的闭环打法

Startup AI自动化落地实战:客服、库存与决策的闭环打法

1. 项目概述:当AI自动化真正落地到 startup 的日常毛细血管里 我带过三支不同阶段的创业团队,从十几人的 SaaS 工具公司,到二十人出头的跨境 DTC 品牌,再到刚完成种子轮的工业 IoT 解决方案团队。过去三年里,我亲手拆过…

2026/7/4 10:13:45 阅读更多 →
ID3到XGBoost:决策树模型演进的工程实战路径

ID3到XGBoost:决策树模型演进的工程实战路径

1. 这不是“树”的科普,而是决策模型演进的实战路线图 你打开任何一本机器学习入门书,十有八九会在第三章遇到“决策树”——画着几根分叉的流程图,讲着信息增益、基尼不纯度这些词,然后戛然而止。但真实项目里,没人只…

2026/7/4 10:13:45 阅读更多 →
十项重塑产业的AI工程突破:从因果推理到边缘大模型

十项重塑产业的AI工程突破:从因果推理到边缘大模型

1. 项目概述:这不是一份“AI新闻简报”,而是一份从业者手写的“技术影响地图”“10 Game-changing AI Breakthroughs Worth Knowing About”——这个标题乍看像科技媒体的年度盘点,但如果你真把它当普通资讯扫一眼就划走,那你就错…

2026/7/4 10:13:45 阅读更多 →
科研信息熵压缩:月度4篇论文精读方法论

科研信息熵压缩:月度4篇论文精读方法论

1. 项目概述:这不是一份文献综述,而是一份科研节奏校准器 “Month in 4 Papers (January 2025)”——这个标题乍看像一份学术期刊的月度简报,但如果你在高校实验室熬过通宵、在工业界赶过模型上线 deadline、或是在读博第三年反复修改 propo…

2026/7/4 10:09:45 阅读更多 →
游戏陪玩App的XSS防御实战:从原理到纵深防护体系构建

游戏陪玩App的XSS防御实战:从原理到纵深防护体系构建

1. 项目概述:为什么游戏陪玩App必须严防XSS?最近在跟一个做游戏陪玩平台的朋友聊技术债,他提到一个让我后背发凉的问题:他们平台上线没多久,就发现有用户在陪玩师的个人简介里,嵌入了能自动跳转到钓鱼网站的…

2026/7/4 10:09:45 阅读更多 →
从零实现大语言模型:Happy-LLM开源教程带你掌握Transformer与微调实战

从零实现大语言模型:Happy-LLM开源教程带你掌握Transformer与微调实战

🚀 30款热门AI模型一站整合,DeepSeek/GLM/Claude 随心用,限时 5 折。 👉 点击领海量免费额度 最近在社区里看到很多朋友对 AI 大模型开发跃跃欲试,但往往被海量的论文、复杂的数学公式和动辄几十个 G 的模型权重劝退…

2026/7/4 10:09:45 阅读更多 →

日新闻

Memcached 1.6.43 发布:关键安全修复版本,多项问题得到解决

Memcached 1.6.43 发布:关键安全修复版本,多项问题得到解决

Memcached 1.6.43 正式发布,这是一个关键的安全修复版本,修复了多个方面的问题,还对部分功能进行了优化。 安全修复亮点 此次发布在安全修复上表现突出。binprot 避免了项目引用计数溢出,mcmc 因安全问题提升了上游版本号&#xf…

2026/7/4 0:04:29 阅读更多 →
终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案

终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案

终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案 【免费下载链接】HMCL A Minecraft Launcher which is multi-functional, cross-platform and popular 项目地址: https://gitcode.com/gh_mirrors/hm/HMCL HMCL(Hello Minecraft! Lau…

2026/7/4 0:06:29 阅读更多 →
KMX63与PIC18F66K40在嵌入式HMI中的硬件协同与低功耗设计

KMX63与PIC18F66K40在嵌入式HMI中的硬件协同与低功耗设计

1. KMX63与PIC18F66K40的硬件协同架构解析KMX63作为一款三轴加速度计和磁力计组合传感器,与PIC18F66K40微控制器的搭配堪称嵌入式HMI开发的黄金组合。这套硬件组合的核心优势在于KMX63提供的高精度运动感知能力与PIC18F66K40强大的信号处理能力形成了完美互补。KMX6…

2026/7/4 0:06:29 阅读更多 →

周新闻

月新闻