mirror of
https://github.com/cheetahlou/CategoryResourceRepost.git
synced 2025-10-20 17:03:47 +08:00
mod
This commit is contained in:
104
极客时间专栏/动态规划面试宝典/课前必读/导读|动态规划问题纷繁复杂,如何系统学习和掌握它?.md
Normal file
104
极客时间专栏/动态规划面试宝典/课前必读/导读|动态规划问题纷繁复杂,如何系统学习和掌握它?.md
Normal file
@@ -0,0 +1,104 @@
|
||||
<audio id="audio" title="导读|动态规划问题纷繁复杂,如何系统学习和掌握它?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/ae/b5/ae7yyc6f97ce7ca86f8d256651de21b5.mp3"></audio>
|
||||
|
||||
你好,我是卢誉声。
|
||||
|
||||
你是否曾经有过,或者正在经历这样的体验,那就是在学习和掌握了一些数据结构和算法后,面对一个较为复杂的面试题,仍然无从下手?
|
||||
|
||||
>
|
||||
<p>那个问题看起来好像可以使用递归,但是我该怎么遍历整个数据结构呢?<br>
|
||||
<br>
|
||||
这个问题看起来需要穷举,但排列组合好像挺难的……<br>
|
||||
<br>
|
||||
这里的排列组合情况实在太多了,我到底该怎么优化时间复杂度?</p>
|
||||
|
||||
|
||||
其实,几乎所有人在初学算法和动态规划时都会有这种感受,特别是当待解决的问题步入“穷举”这个不得了的领域时。穷举从来都不是一个好的解决方案,因此针对这类问题的求解方法真是八仙过海、各显神通,我们很难直接从这些解法中找到规律,同时这些解法又晦涩难懂。
|
||||
|
||||
正因如此,在面试中如果发现问题需要使用穷举或动态规划,很多人就会变得胆战心惊,无从下手。
|
||||
|
||||
但我想告诉你的是,数据结构和算法虽然从表面上看纷繁复杂,但常用的基本思想和方法还真的就不多。这同样适用于动态规划问题,它简直就是模板、套路届的典范。因此,只要我们掌握了正确的学习方法,形成经验式总结,那么当我们再去面对看似“玄幻”的动态规划问题时,就再也不是什么难事了。
|
||||
|
||||
所以说,动态规划作为算法面试问题中的一项重要议题,从表面上看似纷繁复杂,但有规可循。今天,我会把自己这些年来总结的学习窍门、遇到的问题和解题思路,进行归纳总结,梳理出一条清晰的路径给你,即**如何系统学习和掌握动态规划**。我期待这个专栏能让你产生全新的认识,收获清晰的解题思路,轻松跨过大厂算法面试这道坎。
|
||||
|
||||
### 建立扎实的基础知识体系
|
||||
|
||||
首先,我想强调的是,**先掌握基础数据结构和算法,再来谈动态规划。**
|
||||
|
||||
动态规划不仅名字听起来十分高级,它也的确是一种高级的解决问题的思想。为了更好地理解这个思想,掌握基础数据结构就显得尤为重要了,比如高维数组这样的数据结构,就经常出现在动态规划解法当中。其次是算法,像是递归、搜索和迭代这些常见的算法,都会作为工具在动态规划解法中使用。
|
||||
|
||||
这里我再次拿出了开篇词中那张“基石”的图片。没错,你完全可以这样理解:掌握基础数据结构和算法,就是学习动态规划的基石,怎样强调其重要性都不过分。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/8c/f4/8c69611454f088e9458741f55ce138f4.jpg" alt="">
|
||||
|
||||
接着,还有一个值得强调的问题,就是**锻炼算法编码能力**,请不要忽视实践的力量。我曾不止一次在面试环节中,看到面试者在白板上纠结于这样的问题:我是否该在循环上加上等号这个条件?
|
||||
|
||||
1. 加等号?
|
||||
|
||||
```
|
||||
for (int i = 0; i <= MAX_COUNT; i++) { ... }
|
||||
|
||||
```
|
||||
|
||||
1. 还是不加等号?
|
||||
|
||||
```
|
||||
for (int i = 0; i < MAX_COUNT; i++) { ... }
|
||||
|
||||
```
|
||||
|
||||
1. 还是换个方法?
|
||||
|
||||
```
|
||||
for (int i = 0; i < MAX_COUNT + 1; i++) { ... }
|
||||
|
||||
```
|
||||
|
||||
不知道你看到这里,是否会心一笑?是的,在面试过程中,白板是没办法拿给我们做现场调试的。因此,能否快速地写出干净漂亮的代码,不仅能让自己的思路愈发清晰,还能尽量避免错误。
|
||||
|
||||
正所谓细节是魔鬼,在平时学习、练习的过程中,你要**重视细节、重视细节、重视细节**,重要的事情说三遍。
|
||||
|
||||
### 透彻理解动态规划的基本方法论
|
||||
|
||||
我刚才有提到,动态规划是一种思想,是一种高级方法。我们说**算法是一种简单的经验总结和套路**。那什么是思想呢?相较于算法,**思想更多的是指导你我来解决问题的**。既然是思想,那这个东西就比较难落实到实践上来。
|
||||
|
||||
为此,我们必须找到一些规律,来指导我们解决动态规划问题。这些规律或特征包括:寻找子问题、递归求解、重叠子问题与无后效性、状态存储。
|
||||
|
||||
如果你完全没有接触过动态规划,你可能会觉得这几个词已经够头疼了,但其实它们都很简单,在接下来的课程里,我会带着你弄清楚这里的每一个概念,同时也要让它们落到实处,看在一个具体动归问题下它们是如何发挥作用的。
|
||||
|
||||
那么在理解这些概念及其背后的深意之后,我们需要对其进行归纳总结。这么做的主要目的在于,你可以拥有一个清晰的判断标准:**哪些问题应该使用动态规划来解,而哪些不应该或不能使用动态规划来解**。避免盲目地使用动态规划来解题,弄清楚这个问题后,我们才能有的放矢地解决算法难题。
|
||||
|
||||
因此,你完全不需要担心,我们的“车”很稳,且车速适中。
|
||||
|
||||
### 掌握经典问题,总结解题思路
|
||||
|
||||
掌握经典的动态规划问题特别重要,因为很多问题都是从这些经典问题延伸出来的,在后面的课程中,你就会看到这一点。
|
||||
|
||||
在你掌握了诸如背包问题、子序列问题或子数组问题之后,你就会发现这些问题都可以进行归纳总结。当然了,作为专栏,我会给出详细的经验总结,并在后续课程中的恰当时机给出严格的推导。
|
||||
|
||||
这些经验总结在 90% 以上的情况下都是有效的,易于理解,而且十分适合用来应对面试。所以,我希望你也能在接下来的学习过程中,建立自己的经验总结,这些总结可以是基于这个专栏的经验总结之上的,也可以是你在学习的过程中发现的。
|
||||
|
||||
既然我们主要想解决的问题是面试,那么在学习过程中辅以刷题就十分重要了。首先,在专栏中提到的算法问题,你都应该上手自己去实现一遍,这样比单纯的读效果要好上很多!
|
||||
|
||||
其次,刷题也要讲究一个度,我当然希望你能够轻松应对国内大厂或国际大厂的算法面试环节,但是你还是应该循序渐进,慢慢提升刷题数量和刷题的题目难度。正所谓欲速则不达!
|
||||
|
||||
最后,把每一道题目吃透,记录下编写代码时的思考,以便于在未来复习的过程中加深和巩固。
|
||||
|
||||
话说回来,如果你能认真吃透本专栏讲解的题目和经验总结,那么就足以应对这些面试了。
|
||||
|
||||
### 及时总结,举一反三
|
||||
|
||||
其实吧,我们常说人工智能是人工智障,这么说并不过分,因为计算机真的很笨,它唯一能解决的问题就是穷举。对,你没有听错,它只能穷举所有可能性。
|
||||
|
||||
动态规划的思想是从一系列算法中演进而来的。贪心算法是求解整体最优的真正思路源头,我们从那里开始,考虑穷举的问题,最终通过优化形成了一个比较完美的总结。而这个总结,正是动态规划思想。
|
||||
|
||||
所以你看,即便是高级如动态规划这样的思想,也是通过不断的总结而得到的。而经过我们前面这一系列的总结,便形成了下面这幅脑图,你可以通过这幅图对学习动态规划有一个全面的了解。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/56/0f/5605585d75b8ef128285bea9a7c86d0f.jpg" alt="">
|
||||
|
||||
我刚才就提到了总结解题思路,那么除了本专栏为你总结的经验和解题模板之外,我建议你也在学完每一课之后记录下自己的理解。
|
||||
|
||||
我有一个习惯,就是在刷题之后会把关键信息做一个总结,然后分享到刷题网站上。随着时间的推移,有些分享会被人点赞。虽然只是一个不起眼的点赞,但真落到你身上时,它还是会成为一个积极的推动力,会莫名地鼓励你在以后的刷题过程中继续分享观点。就算观点不对,有人给你指了出来,岂不也是一次免费的学习机会?
|
||||
|
||||
而这个专栏就为大家提供了一个很好的交流平台,我期待着你能把经验总结和思考,抑或是问题分享出来,让大家一起学习探讨。让总结、分享成为一个习惯,形成正向刺激。
|
||||
|
||||
那不如就从今天开始,先分享分享你的学习计划吧?让我们一起开启这趟有趣的动态规划学习之旅。
|
89
极客时间专栏/动态规划面试宝典/课前必读/开篇词|为什么大厂都爱考动态规划?.md
Normal file
89
极客时间专栏/动态规划面试宝典/课前必读/开篇词|为什么大厂都爱考动态规划?.md
Normal file
@@ -0,0 +1,89 @@
|
||||
<audio id="audio" title="开篇词|为什么大厂都爱考动态规划?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/64/d7/6454c3ffffab4fec188ab0836eb5d5d7.mp3"></audio>
|
||||
|
||||
你好,我是卢誉声,很高兴能在这个专栏与你见面,和你一起搞定动态规划。
|
||||
|
||||
开门见山,我先做一个自我介绍。最开始,我在思科系统(Cisco Systems)工作,曾参与设计和开发了下一代视频会议系统的核心数据交换服务。我的工作涵盖了协议栈开发、微服务设计、分布式系统编配以及弹性算法设计。
|
||||
|
||||
这段经历让我形成了一个认知:算法对设计关键服务来说十分重要,它决定了系统的稳定性、弹性以及可扩展性。
|
||||
|
||||
后来,我加入了 Autodesk,成为了一款三维设计旗舰软件的框架和平台软件工程师。负责开发了基于大规模结构化数据的高性能搜索引擎,首次将灵活的多线程和异步框架带入产品框架层面,在原有的底层内存模型上采用了改进后的检索引擎,相较于原有的搜索功能,实现了超过 300 倍的性能提升。除此之外,我还改进并维护了用于改进用户体验的数据处理系统,在平台框架层面的工作,让我积累了大量的工程实践经验。
|
||||
|
||||
现在,我在 Autodesk 数据平台就职,负责设计和开发大规模数据的分析、丰富化以及流化分布式服务。
|
||||
|
||||
我发现自己的职业发展一直围绕着数据在不断前进。基于此,我常说的一句话是:“**数据即是正义**”。
|
||||
|
||||
那直到今天,我的态度依然没有变。数据为媒,算法为介,而在极其重要的算法中,动态规划其实占了很大的比重。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/c4/a3/c43bc5fyy622d4f5d3240173b28bb5a3.png" alt="">
|
||||
|
||||
事实上,如果你平常关注大厂面试的话,你会发现,但凡是研发岗位,无论是招聘初级还是高级工程师,大厂都倾向于安排一轮或多轮专门的算法面试环节,而且在面试环节提出动态规划相关问题的这种趋势已经愈发明显。
|
||||
|
||||
这是为什么呢?我来谈谈我的看法。
|
||||
|
||||
先说算法这件事吧。我想请你回想一下,当处理数据结构相关的问题时,你有没有这样的经历?
|
||||
|
||||
1. 你本能地到工具函数或者库函数中寻找有没有现成的工具。如果问题得到快速解决,它是不是迅速就成了过眼云烟?
|
||||
1. 如果这个问题看起来比较棘手,它不是一个典型的算法问题,那么就寻求搜索引擎的帮助,或者干脆访问 Stack Overflow 这样的“智库”寻找前人留下的解决方案?
|
||||
1. 虽然平时工作中表现优异,但当你想换工作参加大厂面试时,又发现自己难以解决面试官提出的算法问题,无从下手,面对白板“望洋兴叹”?
|
||||
|
||||
相信我,你不是一个人!这种现象很普遍。
|
||||
|
||||
其实,对于开发人员来说,算法和数据结构就是我们的基本功。我们常常自嘲软件研发人员的工作就是复制粘贴,搬砖就是日常工作的全部。但当公司或部门要求你去研究一个全新的技术,或者快速阅读一份开发多年且成熟的开源项目代码,并对其改造来服务于自己的产品功能时,你的压力会让你明白基本功到底有多重要!
|
||||
|
||||
关于基本功这事儿,我要插个故事进来,再多说几句。我曾有幸与 C++ 之父 Bjarne Stroustrup 先生进行过面对面的交流。我问了他一个问题:“如今新生代技术人员倾向于学习 Java、Go 或 Python 这些更容易上手的编程语言,您是如何看待这个现象的?”Stroustrup 先生的回答大概是这样的:“如果一个人只了解一种编程语言,那么他不能称自己是专业人士,而从我的角度上看,将 C++ 作为基础,能让你深入洞察各种各样编程语言背后的思想和设计思路。”
|
||||
|
||||
我觉得这个回答特别好。首先,众所周知 C++ 不是一门易学的编程语言,因此,基础不代表简单或容易。其次,C++ 能够极度自由地操纵内存资源,如果你有 C++ 的编程基础,那么在学习 Java 时就会对内存管理和控制有更深的见地。
|
||||
|
||||
和你分享这个小故事,当然不是强调 C++ 的重要性了,但如果你有精力学习 C++ 的话肯定能给你带来数不清的好处。其实,我这里真正想表达的就一点:**掌握好基础,能极大地拓宽我们学习更多新事物、新技术的能力。**
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/8c/f4/8c69611454f088e9458741f55ce138f4.jpg" alt="">
|
||||
|
||||
而算法就像技术领域的基石,它的稳定与否直接决定了大楼最终的高度。那动态规划又起到了什么作用呢?
|
||||
|
||||
我作为面试官曾接触过许多优秀的候选人,他们有着各种各样的背景,既有潜力又非常努力,但在面对算法问题和解决问题时没有太多思路,始终无法更上一层楼,十分遗憾。
|
||||
|
||||
而动态规划恰恰是解决问题的重要方法论,面对很多数据处理的应用场景,它在降低时间复杂度上极具优势,因此成为了考察重点。不仅如此,动态规划问题还能很好地考察面试者的数学模型抽象能力和逻辑思维能力,可以反应个人在算法上的综合能力。
|
||||
|
||||
所以我觉得,大厂之所以如此看中一个面试者的算法基础,**特别是动态规划问题的解决能力,是因为他们更加看中一位面试者解决问题的思路与逻辑思维能力**,而不只是工具与技能的熟练程度。
|
||||
|
||||
讲到这儿,可能有同学会想:虽然大厂爱考,但是这东西会不会就是个绣花枕头?只是在面试中有用,实际工作中用得上吗?
|
||||
|
||||
不同于普通算法,如排序或递归,动态规划从名字上看就显得很特别,有些“高端、大气、上档次”的味道在里面。但其实它离我们很近。我举个例子你就明白了,在云计算平台上一个解决方案的计算能力(容量)肯定是有限的,那么为了高效服务那些重要程度或优先级最高的客户,同时又不想浪费计算资源(说白了为了省钱),我们该怎么办?
|
||||
|
||||
这个问题其实可以通过队列这样的分发方式来进行一个简单的编配。但是这不够好,如果我们能够事先知道一个计算任务的重要程度和所需的计算时长,就可以通过动态规划算法来进行预演算,从数学角度推导出一个严谨的编排结果,实现有限资源的最大化利用。
|
||||
|
||||
你看,似乎遥不可及的动态规划问题,其实就是求最优解问题,它无时无刻都在我们身边,**总是戏剧般地提高了最优化问题的性能!**这再一次凸显出大厂为何青睐于动态规划问题,而且成为了区别面试者的一个隐形门槛。甚至可以说,掌握动态规划思想,在工作面试、技术等级晋升上都扮演了核心角色。总之一句话,动归必学。
|
||||
|
||||
说到这儿,估计又有同学会问:我现在知道动态规划很重要了,面试会考,工程实践要用,但问题是这玩意儿真的难啊,怎么学?
|
||||
|
||||
确实,如果你尝试去搜索引擎上搜动态规划的话,你会发现,检索出来的内容往往比较凌乱,很难有一个系统的方法带你从入门到精通。而像“算法面试”这样的传统书籍,对动态规划问题的描述也比较匮乏,缺乏实战经验,阅读和学习起来枯燥无味,过目就忘。
|
||||
|
||||
说实话,我以前也有过这种困扰。不过,近些年来在工作中用到动态规划的场景越来越多,在积累了大量的实战经验后,再结合上面试经历,我发现还真的可以做一个较为系统的专题,针对动态规划面试题做一次深入的探讨,也就有了这门课。
|
||||
|
||||
我希望这个专栏,能够为你提供一个较为全面的**动态规划知识库**,兼顾理论基础和有效的经验总结,而非照本宣科的理论描述。同时,我也希望它能够为你提供一条捷径,帮助你更快地掌握动态规划问题,从容地应对面试。
|
||||
|
||||
为此,我精心打磨了以下三个模块。
|
||||
|
||||
**模块一:初识动态规划**
|
||||
|
||||
我会为你讲解复杂面试题的思考和解决方式。从贪心算法开始,一步步阐述动态规划的由来,并通过一个贯穿全篇的例子来展现动态规划的强大之处。学习和掌握这些经典的处理方法,能够为你后续掌握动态规划打下一个坚实基础。
|
||||
|
||||
通过这部分内容,你会系统了解到动态规划问题的特点和解题经验。
|
||||
|
||||
**模块二:动态规划的套路**
|
||||
|
||||
我会为你讲解动态规划问题的解题框架和套路,你可以把这个套路理解成是解决动归问题的模板。在此模板的基础上,我会向你讲解面试真题,有针对性地套用解题框架。而应对面试题的纷繁复杂,我会为你进行有效的分类,并针对每一种动态规划问题进行深入而全面的讲解。
|
||||
|
||||
通过这部分内容,你会快速掌握常见面试题的解题套路。
|
||||
|
||||
**模块三:举一反三,突破套路**
|
||||
|
||||
我会针对几种特别易考的动态规划面试题进行总结,帮助你攻破套路。并在这些高级话题的基础上,提出设计动态规划算法的关键问题。另外,还有刷题指南,所谓孰能生巧,必要的练习我们还是要的。
|
||||
|
||||
通过这部分内容,你会快速掌握动态规划面试题的进阶法门。
|
||||
|
||||
最后,我十分理解,动态规划是绝大多数人在面试中的一个老大难问题。有很多人因为它停了下来,错失了机会。掌握动态规划算法,无论是从工程实践还是面试上来说,都充满必要性。所谓大厂,带给我们的不仅仅是品牌光环那么简单,更多的是人生的一个全新阶段和崭新的台阶。
|
||||
|
||||
我希望,这个专栏不仅能帮你跨过大厂算法面试这道坎,还能帮你掌握一套学习复杂知识理论的思维方法,陪你度过职业发展甚至人生的重要时刻!
|
||||
|
||||
关于动态规划,在这里你尽可以畅所欲言,提出你的困惑和问题,非常欢迎你能与我同乘一辆车。一起加油吧!
|
Reference in New Issue
Block a user