Share E-Book

Hello算法 C++版本 (靳宇栋) (Z-Library)

Author 靳宇栋

Science
Language Chinese

No Description

Format PDF
Size 17.6 MB
385
Views
2
Downloads
0.00
Total Donations
(First 20 pages)

Registered users can read the full content for free

Register as a Gaohf Library member to read the complete e-book online for free and enjoy a better reading experience.

Page 1
(This page has no text content)
Page 2
Hello算法 C++语言版 作者:靳宇栋(@krahets) 代码审阅:宫兰景(@Gonglja) Release 1.0.0 2024‑02‑09
Page 3
序 两年前,我在力扣上分享了“剑指Offer”系列题解,受到了许多读者的鼓励和支持。在与读者交流期间,我 最常被问的一个问题是“如何入门算法”。逐渐地,我对这个问题产生了浓厚的兴趣。 两眼一抹黑地刷题似乎是最受欢迎的方法,简单、直接且有效。然而刷题就如同玩“扫雷”游戏,自学能力 强的人能够顺利将地雷逐个排掉,而基础不足的人很可能被炸得满头是包,并在挫折中步步退缩。通读教材 也是一种常见做法,但对于面向求职的人来说,毕业论文、投递简历、准备笔试和面试已经消耗了大部分精 力,啃厚重的书往往变成了一项艰巨的挑战。 如果你也面临类似的困扰,那么很幸运这本书“找”到了你。本书是我对这个问题给出的答案,即使不是最 优解,也至少是一次积极的尝试。本书虽然不足以让你直接拿到 Offer,但会引导你探索数据结构与算法的 “知识地图”,带你了解不同“地雷”的形状、大小和分布位置,让你掌握各种“排雷方法”。有了这些本领, 相信你可以更加自如地刷题和阅读文献,逐步构建起完整的知识体系。 我深深赞同费曼教授所言:“Knowledge isn’t free. You have to pay attention.”从这个意义上看,这本 书并非完全“免费”。为了不辜负你为本书所付出的宝贵“注意力”,我会竭尽所能,投入最大的“注意力” 来完成本书的创作。本人自知学疏才浅,书中内容虽然已经过一段时间的打磨,但一定仍有许多错误,恳请 各位老师和同学批评指正。 本书中的代码附有可一键运行的源文件,托管于 github.com/krahets/hello‑algo 仓库。动画在 PDF 内的 展示效果受限,可访问 hello‑algo.com网页版以获得更优的阅读体验。 推荐语 “一本通俗易懂的数据结构与算法入门书,引导读者手脑并用地学习,强烈推荐算法初学者阅读!” ——邓俊辉,清华大学计算机系教授 “如果我当年学数据结构与算法的时候有《Hello 算法》,学起来应该会简单 10 倍!” ——李沐,亚马逊资深首席科学家
Page 4
i 目 录 第0章 前言 1 0.1 关于本书 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 0.2 如何使用本书 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 0.3 小结 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 第1章 初识算法 10 1.1 算法无处不在 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 1.2 算法是什么 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 1.3 小结 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 第2章 复杂度分析 17 2.1 算法效率评估 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 2.2 迭代与递归 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 2.3 时间复杂度 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 2.4 空间复杂度 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 2.5 小结 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 第3章 数据结构 51 3.1 数据结构分类 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 3.2 基本数据类型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 3.3 数字编码 * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 3.4 字符编码 * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 3.5 小结 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 第4章 数组与链表 66 4.1 数组 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 4.2 链表 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 4.3 列表 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 4.4 内存与缓存 * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83 4.5 小结 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86 第5章 栈与队列 89 5.1 栈 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90 5.2 队列 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 5.3 双向队列 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 5.4 小结 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 第6章 哈希表 114 6.1 哈希表 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 6.2 哈希冲突 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 6.3 哈希算法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130 6.4 小结 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 第7章 树 137 7.1 二叉树 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 7.2 二叉树遍历 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 7.3 二叉树数组表示 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148 7.4 二叉搜索树 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 7.5 AVL 树 * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 7.6 小结 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
Page 5
目 录 hello‑algo.com ii 第8章 堆 173 8.1 堆 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174 8.2 建堆操作 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181 8.3 Top‑k 问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184 8.4 小结 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187 第9章 图 188 9.1 图 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189 9.2 图的基础操作 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193 9.3 图的遍历 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199 9.4 小结 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206 第10章 搜索 208 10.1 二分查找 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209 10.2 二分查找插入点 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212 10.3 二分查找边界 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216 10.4 哈希优化策略 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219 10.5 重识搜索算法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 10.6 小结 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223 第11章 排序 225 11.1 排序算法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226 11.2 选择排序 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227 11.3 冒泡排序 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230 11.4 插入排序 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232 11.5 快速排序 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235 11.6 归并排序 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240 11.7 堆排序 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243 11.8 桶排序 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246 11.9 计数排序 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249 11.10 基数排序 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254 11.11 小结 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256 第12章 分治 259 12.1 分治算法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260 12.2 分治搜索策略 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263 12.3 构建二叉树问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265 12.4 汉诺塔问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270 12.5 小结 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274 第13章 回溯 276 13.1 回溯算法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277 13.2 全排列问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285 13.3 子集和问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290 13.4 n 皇后问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297 13.5 小结 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301 第14章 动态规划 302 14.1 初探动态规划 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 303 14.2 动态规划问题特性 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 309 14.3 动态规划解题思路 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314 14.4 0‑1 背包问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 322 14.5 完全背包问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329 14.6 编辑距离问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 339 14.7 小结 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345
Page 6
目 录 hello‑algo.com iii 第15章 贪心 346 15.1 贪心算法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347 15.2 分数背包问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350 15.3 最大容量问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354 15.4 最大切分乘积问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359 15.5 小结 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362 第16章 附录 364 16.1 编程环境安装 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 365 16.2 一起参与创作 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367 16.3 术语表 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 369
Page 7
1 第0章 前言 算法犹如美妙的交响乐,每一行代码都像韵律般流淌。 愿这本书在你的脑海中轻轻响起,留下独特而深刻的旋律。
Page 8
第 0章 前言 hello‑algo.com 2 0.1 关于本书 本项目旨在创建一本开源、免费、对新手友好的数据结构与算法入门教程。 ‧ 全书采用动画图解,结构化地讲解数据结构与算法知识,内容清晰易懂,学习曲线平滑。 ‧ 算法源代码皆可一键运行,支持Python、C++、Java、C#、Go、Swift、JavaScript、TypeScript、Dart、 Rust、C 和 Zig 等语言。 ‧ 鼓励读者在线上章节评论区互帮互助、共同进步,提问与评论通常可在两日内得到回复。 0.1.1 读者对象 若你是算法初学者,从未接触过算法,或者已经有一些刷题经验,对数据结构与算法有模糊的认识,在会与 不会之间反复横跳,那么本书正是为你量身定制的! 如果你已经积累一定的刷题量,熟悉大部分题型,那么本书可助你回顾与梳理算法知识体系,仓库源代码可 以当作“刷题工具库”或“算法字典”来使用。 若你是算法“大神”,我们期待收到你的宝贵建议,或者一起参与创作。 前置条件 你需要至少具备任一语言的编程基础,能够阅读和编写简单代码。 0.1.2 内容结构 本书的主要内容如图 0‑1 所示。 ‧ 复杂度分析:数据结构和算法的评价维度与方法。时间复杂度和空间复杂度的推算方法、常见类型、示 例等。 ‧ 数据结构:基本数据类型和数据结构的分类方法。数组、链表、栈、队列、哈希表、树、堆、图等数据 结构的定义、优缺点、常用操作、常见类型、典型应用、实现方法等。 ‧ 算法:搜索、排序、分治、回溯、动态规划、贪心等算法的定义、优缺点、效率、应用场景、解题步骤 和示例问题等。
Page 9
第 0章 前言 hello‑algo.com 3 图 0‑1 本书主要内容 0.1.3 致谢 本书在开源社区众多贡献者的共同努力下不断完善。感谢每一位投入时间与精力的撰稿人,他们是(按照 GitHub自动生成的顺序):krahets、codingonion、nuomi1、Gonglja、Reanon、justin‑tse、danielsss、 hpstory、S‑N‑O‑R‑L‑A‑X、night‑cruise、msk397、gvenusleo、RiverTwilight、gyt95、zhuoqinyue、 Zuoxun、Xia‑Sang、mingXta、FangYuan33、GN‑Yu、IsChristina、xBLACKICEx、guowei‑gong、Cathay‑ Chen、mgisr、JoseHung、qualifier1024、pengchzn、Guanngxu、longsizhuo、L‑Super、what‑is‑me、 yuan0221、lhxsm、Slone123c、WSL0809、longranger2、theNefelibatas、xiongsp、JeffersonHuang、 hongyun‑robot、K3v123、yuelinxin、a16su、gaofer、malone6、Wonderdch、xjr7670、DullSword、 Horbin‑Magician、NI‑SW、reeswell、XC‑Zero、XiaChuerwu、yd‑j、iron‑irax、huawuque404、MolDuM、 Nigh、KorsChen、foursevenlove、52coder、bubble9um、youshaoXG、curly210102、gltianwen、 fanchenggang、Transmigration‑zhou、FloranceYeh、FreddieLi、ShiMaRing、lipusheng、Javesun99、 JackYang‑hellobobo、shanghai‑Jerry、0130w、Keynman、psychelzh、logan‑qiu、ZnYang2018、 MwumLi、1ch0、Phoenix0415、qingpeng9802、Richard‑Zhang1019、QiLOL、Suremotoo、Turing‑ 1024‑Lee、Evilrabbit520、GaochaoZhu、ZJKung、linzeyan、hezhizhen、ZongYangL、beintentional、 czruby、coderlef、dshlstarr、szu17dmy、fbigm、gledfish、hts0000、boloboloda、iStig、jiaxianhua、 wenjianmin、keshida、kilikilikid、lclc6、lwbaptx、liuxjerry、lucaswangdev、lyl625760、chadyi、 noobcodemaker、selear、siqyka、syd168、4yDX3906、tao363、wangwang105、weibk、yabo083、 yi427、yishangzhang、zhouLion、baagod、ElaBosak233、xb534、luluxia、yanedie、thomasq0、 YangXuanyi 和 th1nk3r‑ing 。
Page 10
第 0章 前言 hello‑algo.com 4 本书的代码审阅工作由codingonion、Gonglja、gvenusleo、hpstory、justin‑tse、krahets、night‑cruise、 nuomi1 和 Reanon 完成(按照首字母顺序排列)。感谢他们付出的时间与精力,正是他们确保了各语言代 码的规范与统一。 在本书的创作过程中,我得到了许多人的帮助。 ‧ 感谢我在公司的导师李汐博士,在一次畅谈中你鼓励我“快行动起来”,坚定了我写这本书的决心; ‧ 感谢我的女朋友泡泡作为本书的首位读者,从算法小白的角度提出许多宝贵建议,使得本书更适合新 手阅读; ‧ 感谢腾宝、琦宝、飞宝为本书起了一个富有创意的名字,唤起大家写下第一行代码“Hello World!”的 美好回忆; ‧ 感谢校铨在知识产权方面提供的专业帮助,这对本开源书的完善起到了重要作用; ‧ 感谢苏潼为本书设计了精美的封面和 logo ,并在我的强迫症的驱使下多次耐心修改; ‧ 感谢@squidfunk 提供的排版建议,以及他开发的开源文档主题Material‑for‑MkDocs 。 在写作过程中,我阅读了许多关于数据结构与算法的教材和文章。这些作品为本书提供了优秀的范本,确保 了本书内容的准确性与品质。在此感谢所有老师和前辈的杰出贡献! 本书倡导手脑并用的学习方式,在这一点上我深受《动手学深度学习》的启发。在此向各位读者强烈推荐这 本优秀的著作。 衷心感谢我的父母,正是你们一直以来的支持与鼓励,让我有机会做这件富有趣味的事。 0.2 如何使用本书 为了获得最佳的阅读体验,建议你通读本节内容。 0.2.1 行文风格约定 ‧ 标题后标注 *的是选读章节,内容相对困难。如果你的时间有限,可以先跳过。 ‧ 重要专有名词及其英文翻译会用「」括号标注,例如「数组 array」。建议记住它们,以便阅读文献。 ‧ 专有名词和有特指含义的词句会使用“引号”标注,以避免歧义。 ‧ 重要名词、重点内容和总结性语句会加粗,这类文字值得特别关注。 ‧ 当涉及编程语言之间不一致的名词时,本书均以 Python 为准,例如使用 None来表示“空”。 ‧ 本书部分放弃了编程语言的注释规范,以换取更加紧凑的内容排版。注释主要分为三种类型:标题注 释、内容注释、多行注释。 /* 标题注释,用于标注函数、类、测试样例等 */ // 内容注释,用于详解代码 /** * 多行
Page 11
第 0章 前言 hello‑algo.com 5 * 注释 */ 0.2.2 在动画图解中高效学习 相较于文字,视频和图片具有更高的信息密度和结构化程度,更易于理解。在本书中,重点和难点知识将主 要通过动画以图解形式展示,而文字则作为解释与补充。 如果你在阅读本书时,发现某段内容提供了如图 0‑2 所示的动画图解,请以图为主、以文字为辅,综合两者 来理解内容。 图 0‑2 动画图解示例 0.2.3 在代码实践中加深理解 本书的配套代码托管在GitHub 仓库。如图 0‑3 所示,源代码附有测试样例,可一键运行。 如果时间允许,建议你参照代码自行敲一遍。如果学习时间有限,请至少通读并运行所有代码。 与阅读代码相比,编写代码的过程往往能带来更多收获。动手学,才是真的学。
Page 12
第 0章 前言 hello‑algo.com 6 图 0‑3 运行代码示例 运行代码的前置工作主要分为三步。 第一步:安装本地编程环境。请参照附录所示的教程进行安装,如果已安装,则可跳过此步骤。 第二步:克隆或下载代码仓库。前往GitHub 仓库。如果已经安装Git ,可以通过以下命令克隆本仓库: git clone https://github.com/krahets/hello-algo.git 当然,你也可以在图 0‑4 所示的位置,点击“Download ZIP”按钮直接下载代码压缩包,然后在本地解压即 可。
Page 13
第 0章 前言 hello‑algo.com 7 图 0‑4 克隆仓库与下载代码 第三步:运行源代码。如图 0‑5 所示,对于顶部标有文件名称的代码块,我们可以在仓库的 codes文件夹内 找到对应的源代码文件。源代码文件可一键运行,将帮助你节省不必要的调试时间,让你能够专注于学习内 容。 图 0‑5 代码块与对应的源代码文件 除了本地运行代码,网页版还支持Python代码的可视化运行(基于pythontutor 实现)。如图 0‑6 所示,你 可以点击代码块下方的“可视化运行”来展开视图,观察算法代码的执行过程;也可以点击“全屏观看”,以 获得更好的阅览体验。 图 0‑6 Python 代码的可视化运行
Page 14
第 0章 前言 hello‑algo.com 8 0.2.4 在提问讨论中共同成长 在阅读本书时,请不要轻易跳过那些没学明白的知识点。欢迎在评论区提出你的问题,我和小伙伴们将竭诚 为你解答,一般情况下可在两天内回复。 如图 0‑7 所示,网页版每个章节的底部都配有评论区。希望你能多关注评论区的内容。一方面,你可以了解 大家遇到的问题,从而查漏补缺,激发更深入的思考。另一方面,期待你能慷慨地回答其他小伙伴的问题,分 享你的见解,帮助他人进步。 图 0‑7 评论区示例 0.2.5 算法学习路线 从总体上看,我们可以将学习数据结构与算法的过程划分为三个阶段。 1. 阶段一:算法入门。我们需要熟悉各种数据结构的特点和用法,学习不同算法的原理、流程、用途和效 率等方面的内容。 2. 阶段二:刷算法题。建议从热门题目开刷,如“剑指Offer”和“LeetCode Hot 100”,先积累至少 100 道题目,熟悉主流的算法问题。初次刷题时,“知识遗忘”可能是一个挑战,但请放心,这是很正常的。 我们可以按照“艾宾浩斯遗忘曲线”来复习题目,通常在进行 3~5 轮的重复后,就能将其牢记在心。 3. 阶段三:搭建知识体系。在学习方面,我们可以阅读算法专栏文章、解题框架和算法教材,以不断丰富 知识体系。在刷题方面,可以尝试采用进阶刷题策略,如按专题分类、一题多解、一解多题等,相关的 刷题心得可以在各个社区找到。 如图 0‑8 所示,本书内容主要涵盖“阶段一”,旨在帮助你更高效地展开阶段二和阶段三的学习。
Page 15
第 0章 前言 hello‑algo.com 9 图 0‑8 算法学习路线 0.3 小结 ‧ 本书的主要受众是算法初学者。如果你已有一定基础,本书能帮助你系统回顾算法知识,书中源代码也 可作为“刷题工具库”使用。 ‧ 书中内容主要包括复杂度分析、数据结构和算法三部分,涵盖了该领域的大部分主题。 ‧ 对于算法新手,在初学阶段阅读一本入门书至关重要,可以少走许多弯路。 ‧ 书中的动画图解通常用于介绍重点和难点知识。阅读本书时,应给予这些内容更多关注。 ‧ 实践乃学习编程之最佳途径。强烈建议运行源代码并亲自敲代码。 ‧ 本书网页版的每个章节都设有评论区,欢迎随时分享你的疑惑与见解。
Page 16
10 第1章 初识算法 一位少女翩翩起舞,与数据交织在一起,裙摆上飘扬着算法的旋律。 她邀请你共舞,请紧跟她的步伐,踏入充满逻辑与美感的算法世界。
Page 17
第 1章 初识算法 hello‑algo.com 11 1.1 算法无处不在 当我们听到“算法”这个词时,很自然地会想到数学。然而实际上,许多算法并不涉及复杂数学,而是更多 地依赖基本逻辑,这些逻辑在我们的日常生活中处处可见。 在正式探讨算法之前,有一个有趣的事实值得分享:你已经在不知不觉中学会了许多算法,并习惯将它们应 用到日常生活中了。下面我将举几个具体的例子来证实这一点。 例一:查字典。在字典里,每个汉字都对应一个拼音,而字典是按照拼音字母顺序排列的。假设我们需要查 找一个拼音首字母为 𝑟的字,通常会按照图 1‑1 所示的方式实现。 1. 翻开字典约一半的页数,查看该页的首字母是什么,假设首字母为𝑚。 2. 由于在拼音字母表中 𝑟位于𝑚之后,所以排除字典前半部分,查找范围缩小到后半部分。 3. 不断重复步骤 1.和步骤 2.,直至找到拼音首字母为 𝑟的页码为止。 图 1‑1 查字典步骤 查字典这个小学生必备技能,实际上就是著名的“二分查找”算法。从数据结构的角度,我们可以把字典视 为一个已排序的“数组”;从算法的角度,我们可以将上述查字典的一系列操作看作“二分查找”。 例二:整理扑克。我们在打牌时,每局都需要整理手中的扑克牌,使其从小到大排列,实现流程如图 1‑2 所 示。
Page 18
第 1章 初识算法 hello‑algo.com 12 1. 将扑克牌划分为“有序”和“无序”两部分,并假设初始状态下最左 1张扑克牌已经有序。 2. 在无序部分抽出一张扑克牌,插入至有序部分的正确位置;完成后最左 2张扑克已经有序。 3. 不断循环步骤 2.,每一轮将一张扑克牌从无序部分插入至有序部分,直至所有扑克牌都有序。 图 1‑2 扑克排序步骤 上述整理扑克牌的方法本质上是“插入排序”算法,它在处理小型数据集时非常高效。许多编程语言的排序 库函数中都有插入排序的身影。 例三:货币找零。假设我们在超市购买了 69元的商品,给了收银员 100元,则收银员需要找我们 31元。他 会很自然地完成如图 1‑3 所示的思考。 1. 可选项是比 31元面值更小的货币,包括 1元、5元、10元、20元。 2. 从可选项中拿出最大的 20元,剩余 31 − 20 = 11元。 3. 从剩余可选项中拿出最大的 10元,剩余 11 − 10 = 1元。 4. 从剩余可选项中拿出最大的 1元,剩余 1 − 1 = 0元。 5. 完成找零,方案为 20 + 10 + 1 = 31元。
Page 19
第 1章 初识算法 hello‑algo.com 13 图 1‑3 货币找零过程 在以上步骤中,我们每一步都采取当前看来最好的选择(尽可能用大面额的货币),最终得到了可行的找零方 案。从数据结构与算法的角度看,这种方法本质上是“贪心”算法。 小到烹饪一道菜,大到星际航行,几乎所有问题的解决都离不开算法。计算机的出现使得我们能够通过编程 将数据结构存储在内存中,同时编写代码调用 CPU和 GPU执行算法。这样一来,我们就能把生活中的问题 转移到计算机上,以更高效的方式解决各种复杂问题。 如果你对数据结构、算法、数组和二分查找等概念仍感到一知半解,请继续往下阅读,本书将 引导你迈入数据结构与算法的知识殿堂。 1.2 算法是什么 1.2.1 算法定义 「算法 algorithm」是在有限时间内解决特定问题的一组指令或操作步骤,它具有以下特性。 ‧ 问题是明确的,包含清晰的输入和输出定义。 ‧ 具有可行性,能够在有限步骤、时间和内存空间下完成。 ‧ 各步骤都有确定的含义,在相同的输入和运行条件下,输出始终相同。 1.2.2 数据结构定义 「数据结构 data structure」是计算机中组织和存储数据的方式,具有以下设计目标。 ‧ 空间占用尽量少,以节省计算机内存。
Page 20
第 1章 初识算法 hello‑algo.com 14 ‧ 数据操作尽可能快速,涵盖数据访问、添加、删除、更新等。 ‧ 提供简洁的数据表示和逻辑信息,以便算法高效运行。 数据结构设计是一个充满权衡的过程。如果想在某方面取得提升,往往需要在另一方面作出妥协。下面举两 个例子。 ‧ 链表相较于数组,在数据添加和删除操作上更加便捷,但牺牲了数据访问速度。 ‧ 图相较于链表,提供了更丰富的逻辑信息,但需要占用更大的内存空间。 1.2.3 数据结构与算法的关系 如图 1‑4 所示,数据结构与算法高度相关、紧密结合,具体表现在以下三个方面。 ‧ 数据结构是算法的基石。数据结构为算法提供了结构化存储的数据,以及操作数据的方法。 ‧ 算法是数据结构发挥作用的舞台。数据结构本身仅存储数据信息,结合算法才能解决特定问题。 ‧ 算法通常可以基于不同的数据结构实现,但执行效率可能相差很大,选择合适的数据结构是关键。 图 1‑4 数据结构与算法的关系 数据结构与算法犹如图 1‑5 所示的拼装积木。一套积木,除了包含许多零件之外,还附有详细的组装说明书。 我们按照说明书一步步操作,就能组装出精美的积木模型。
The above is a preview of the first 20 pages. Register to read the complete e-book.

Recommended for You

Loading recommended books...
Failed to load, please try again later

Tip the Site

Scan the WeChat Pay or Alipay code to tip. No login required.

WeChat Pay
Alipay
Back to List