本书归纳了程序员面试中的经典算法题,并按照由浅入深、循序渐进的顺序讲解。
本书首先讲解程序员面试时需要了解的制作简历的技巧和IT名企的面试流程,以及面试时经常忽略的代码规范性问题。然后详细分析程序的时间复杂度和空间复杂库,包括如何把控程序的实际运行时间,以及编程语言的内存管理。接着讲解数组、链表、哈希表、字符串、栈与队列、二叉树、回溯算法、贪心算法、动态规划的理论基础及其相关题目。
本书采用了力扣(LeetCode)的原题,方便读者在学习算法的同时,及时练习相关代码,加深对相关概念的理解。
本书适合所有程序员阅读,特别是正在准备面试的程序员。希望本书可以帮助读者循序渐进地学习算法,并搭建起知识框架,提升算法功力。
本书采用了力扣(LeetCode)的原题,方便读者在学习算法的同时,及时练习相关代码,加深对相关概念的理解。
前言
算法是无数计算机先贤们的智慧结晶。当我们遇到生活中几乎无解的问题时,如果能利用相关算法,通过几行代码就可以轻松求出结果,那一刻将会感受到算法的美妙与神奇。
而我也被这一魔力所吸引。
十年前我开始学习算法,并且开始写与算法相关的博客。当时写算法博客的人还不多,网上能搜索到的算法文章也有限。
很多人没有写博客的习惯,因为写博客在一定程度上确实“耽误时间”。
不过当时我只是想记录下来,想着以后如果把这些知识都忘了,至少博客可以证明:曾经我掌握过。
没想到,算法陪伴我一晃就是十年,从本科到研究生,从一家公司到另一家公司,再到算法图书的出版……我的每一段人生经历都在从不同的角度和算法打交道。
随着多年学习和实践,我在各种在线判题平台上已经积累了上千题,对算法的理解已经有一套独特的体系。
同时我也发现,很多读者在刷题和学习算法时,真正的苦恼在于没有一套行之有效的刷题顺序。
例如,动态规划是公认的程序员面试里最难掌握的算法,也是出现频率最高的算法。如果仅仅讲解几道题目,即使再举一反三也远远达不到真正理解的程度。如果把动态规划的题目单纯地堆砌在一起,也只会让人越学越懵,陷入“一看就会,一写就废”的怪圈。讲清楚一两道题容易,但把整个动态规划的各个分支讲清楚,把每道题目讲透彻,并用一套方法论来指导就有难度了。这既是我无数日夜地伏案思考、反复推理,要帮助读者解决的问题,也是本书的使命所在。
对于动态规划、二叉树、回溯算法等,本书都总结了一套行之有效的方法论,系统性地解决这些算法的相关问题,并把相关题目按照由易到难的顺序编排,让读者循序渐进地征服算法的一座又一座高山。
本书特色
刚开始学习数据结构与算法,或者在力扣(LeetCode)上刷题的读者都有这种困惑——从何学起,先学什么,再学什么。很多人刷题的效率低,主要体现在以下三点:
?难以寻找适合自己的题目。
?找到了不合适现阶段做的题目,结果发现毫无头绪。
?没有全套的优质题解可以参考。
我相信很多人对此深有体会,所以我将每一个专题中的题目按照由易到难的顺序进行编排,每一道题目所涉及的知识都会有相应的题目做知识铺垫,做到环环相扣。
建议读者按章节顺序阅读本书,在阅读的过程中会发现题目编排上的良苦用心。
本书不仅在题目编排上精心设计,而且在针对读者最头痛的算法问题上做了详细且深入的讲解。
关于动态规划,都知道递归公式的重要性,但dp数组的含义、dp数组的初始化、遍历顺序都很重要。例如,解决背包问题时,遍历顺序才是最关键的也是最难理解的。
关于回溯算法,不同集合之间需要去重。虽然各种资料都说要去重,但没有说清楚是“树层去重”还是“树枝去重”——这是我为了说明去重的过程而创造的两个词汇。
关于KMP算法,都知道使用next数组进行回退,可根据前缀表生成next数组有很多种方式,却没有说清楚,导致大家看得一头雾水。
关于二叉树,不同的遍历顺序的递归函数究竟如何安排,递归函数什么时候需要返回值,什么时候不用返回值,这些细节都决定了对二叉树的理解是否到位。
本书同时针对每一个专题的特点,整理出其通用的解法套路。例如,在二叉树专题中,总结了递归“三部曲”来帮助读者掌握二叉树中各种遍历方式的写法。回溯算法中的回溯“三部曲”可以帮助读者理解回溯算法晦涩难懂的过程。动态规划中的动规“五部曲”可以帮助读者在一套思考框架下解决所有的动态规划题目。
相信读者耐心看完本书,会对书中介绍的算法有更深层次的理解。
本书配套资源
本书统一使用C++语言进行讲解,对于使用其他语言的读者,可以浏览本书配套网站:programmercarl(com域名)——支持Java、Python、Go、JavaScript等多语言版本,同时一些题目还有动画演示,帮助读者更好地掌握本书内容。
在微信公众号“代码随想录”后台回复“算法学习”,可以加入算法学习交流群,并且获得本书配套学习资料,包含代码、题目大纲等。
我会在B站“代码随想录”定期更新算法视频,相信可以帮助读者更好地理解相关知识。
勘误
个人能力有限,书中难免有疏漏之处,恳请广大读者们批评指正。
在微信公众号“代码随想录”底部的一个菜单中有我的联系方式,如果读者有疑问或者发现了Bug,可以与我联系,我会一一回复。同时我在公众号添加了一个新的菜单入口,更新书中的Bug。
致谢
这里要感谢录友们(“代码随想录”的朋友们,也是公众号“代码随想录”的忠实读者),是你们的支持,让“代码随想录”从无到有,到最后出版成书与读者见面。虽然从未谋面,但通过文字,我们已经交流了整整一年有余。真心地感谢每一位录友。
感谢电子工业出版社的工作人员,特别是陈晓猛编辑。陈编辑认真负责,是非常可靠的合作伙伴。
最后我要感谢我的父母——孙世忠先生和马丽丽女士。我的家乡在黑龙江偏远小镇,父亲长期从事重体力劳动,辛勤劳苦,母亲操持家业,督促我学习。父母在我求学的路上给予了我最大的支持,付出了非常多。我无以为谢,谨以此书献给他们。
孙秀洋(@程序员Carl)
2021年10月11日于深圳南山