PART_2_力扣图解/sourcefile/2.指导学习/021.md
date: 2020-07-01
我自己有个很喜欢的话,叫做 “练习 - 坚持 - 总结 - 提高”,我们已经练习了 70 天,如果不进行一些问题的总结,永远只低头看路,恐怕就会迷路。所以今儿咱们不讲算法题,而是讲一讲到底如何“解决问题”,本文非常非常非常重要,是我很长一段时间的心血与积累,大家一定要耐心看完,共包含3节:
- 算法对个人的意义
- 解决问题的策略
- 算法问题汇总
在实际项目中,算法的使用场景有很多,如“Java8中Hashmap使用红黑树来实现”、“Redis底层使用LRU来进做淘汰策略”、“大数据领域很多问题都基于TopK”、“JS原型链里使了类似链表的成环检测”、“特别复杂的业务逻辑经常涉及到DAG”、“MySql为什么索引要用B+树”、“Oracle里的开窗函数如何实现” 等等等等,这些今天我们统统不谈。而我,更多的是想和大家聊一聊,算法对个人有什么意义?
市面上大部分的算法书籍,第一章介绍算法,都会给大家列一列类似上面的那些话,或者就是使用栈或队列来做一个引子,告诉大家算法很重要,你得需要去学,吧啦吧啦....但是不知道大家有没有想过这样一个问题,算法对于个人而言到底有什么意义呢?如果这个问题大家陌生,那你一定会听到有写了几年业务逻辑的老程序员,说过“我这些年从来没有用过算法,除了出去面试的时候”之类的话。其实,我这里真想说一句脏话,这些思想真的是TMD害人不浅啊。甚至我怀疑大多数说这句话本身的人,有两种:一种就是严重缺乏自信心,觉得自己一辈子都没办法学好算法了,所以就这样吧。第二种就是故意误人子弟,驱动来源于自己不会,方式采用侃大山,反正忽悠一个是一个,再来身边也没有其他这方面厉害的朋友,说完之后自己都没意识到哪里有问题,却对别人带去很不好的影响。所以如果你今天看到我的这篇文章,我希望你能记住一世,这辈子都不要说出这种类似的话来,保持对这个学科基本的尊重,哪怕多一点点匠心精神。算法对个人的意义如下:
总之,正是因为算法题目中只保留了必备的要素,舍弃了其他无关紧要的部分,所以可以对每一位做题人都构建一个学习解决问题的最佳环境,而在这个环境中的成长与提高,将对一个软件工程师的生涯产生深远影响,乃至一世。所以,请大家能有一颗匠心,你可以选择不去了解学习掌握算法,但是请不要耽误他人进步。山高水长,江湖路远,珍重万千,有缘再见!
解决简单的问题时,直接利用已知的技术便可轻松解决问题。但是如果遇到难题,恐怕就需要用各种手段。管他是花猫野猫,抓住耗子都是好猫。在解决问题的策略构建中,我们首先要对问题和答案结构有一个直观的感受,或者说猜测。如果可以把控住当前算法的问题,具备一个什么样的形态,然后就可以把毫无头绪的事情,变得有迹可循。在这样一个过程中,一点点的积累经验,最终就可以提升自己。
上面说的内容,玄而又玄,那到底如何来构建策略。假如我们遇到一个问题,让我们找一个国家铁路网中,两个城市的最短路径。这种问题,大家肯定首先想到的就是使用迪杰斯特拉算法。但是如果问题变成“换乘火车次数少于N次,寻找最短路径”,这种问题将不能直接套用最短路径的算法。有时候只是改变题中条件,就可以让整个题目完全走向另一个逻辑,这就需要大家对原算法的原理和执行过程特别了解,并且熟读题意。所以这里我们抽象出两个步骤:
读题的目的,就是阅读并理解问题。不管是是不是算法老手,在这上面栽跟头的绝对不是一个两个,审题不清是所有人的共性(绝不是你的个人问题),人的天性就期望可以快速得到反馈,这是身体欲望导致的,和你看到漂亮的妹子下半身竖立本质没有什么区别。所以这就引出我们的解决方法 - 重构。
什么是重构,重构其实就是一个抽象化的过程。借用我们已经掌握的数学/计算机知识,将其表达成现实世界概念。大部分的现实世界概念都是比较复杂的,我们对其抽茧剥丝,保留本质,表述成易于理解的形式。而对其重构的过程,就可以决定其程序设计的方向。举一个最简单的例子,比如我们要用代码实现一个整数平方根的开方,可以选用牛顿法或者二分法,那这两种方法是如何被想到的。假如我们把问题重构成图形的表达方式,就比较容易会推出牛顿法。假如我们把问题重构成已有的知识概念,自然就可以想到二分法。而如果我们把问题抽象成公式,甚至可以通过数学法来进行解题。划重点,不同的重构方式,决定最终程序的走向。
在重构的基础上,其实我们就可以来进行解题了。但是这里我还要对其加一个步骤,化简。什么又是化简,如何化简?假如我们有一个题,我们有一个二维网格,里边有N个点,两点的距离是X坐标和Y坐标的的和。比如坐标(5,1)和(4,7)的点间距就是1+6=7。我们要找到给出的N个点距离之和最小的新点的坐标。
题目因为本身是二维的,我们写代码其实不是很好写。所以我们可以将其化简为一维。我们把每一个点的左边,通过映射的方式,分别映射到 x轴 和 y轴。然后我们把问题转化成在直线上寻找到给出点的距离之和最小的点。这就是化简。万物之始,大道至简,至拙至美。生活中咱们也说透过现象看本质,放在算法里你就不会了?
读题-重构-化简,下来自然就是解题了。那如何解题?这个范畴虽然很大,但也不是无迹可寻,下面两点:
基本数据结构和算法的掌握,这个自不必说,是人都知道,那么常见算法问题的汇总又是什么,我们看下一节。
写算法最怕什么?当然是出错。与其重复相同的错误,不如从错误中吸取教训。与其从自己的错误中吸取教训,不如从别人的错误中学习经验。总结常见的算法问题,我总不能和你去说我们需要掌握数组、链表、二叉树、Map等这些数据结构。我认为的总结,就是错误的总结。所以为了快速拔高大家的水准,我准备了以下这些错误,请一定耐心看完,反复阅读。
以上就是我挑选过的一些具有代表性的错误示例(后续还会补充),同时,算法指导篇我打算出一个系列,包括算法中常用技巧,常见错误,题目常见误导 等等,都是我的珍藏。今天的文章呕心泣血,希望大家可以帮我转发,我想如果你身边有学习计算机的朋友看到,他一定会感谢你。支持我的朋友们,还没有关注的,快点来个关注。最后,山高水长,江湖路远,珍重万千,下期再见!