一、搞算法,从一瞬间的热爱开始

我爱创意胜过逻辑,喜欢编写代码超过闷头学习。

当我实现自己的第99个创意之后,看着窗外散发着昏黄光晕的夕阳🌇,心里有一丢丢空虚。

于是,我把目光转向了算法,迟早要刷题,不如趁着这股头脑发热的劲头研究一番。

因为不够专业,才想着提升自己。不想只是略懂皮毛,能通晓原理岂不锦上添花。

那么先来了解一下算法是什么吧。

初探算法之门

算法是指对特定问题求解步骤的一种描述。

使用自然语言、程序设计语言描述算法,也可以使用流程图、框图等图形化的方式来描述算法。

算法特性

  • 有穷性:由若干条指令组成的有穷序列组成,总能在执行若干次后结束算法,算法不是永不停止的。
  • 确定性:算法中的每条语句都是有明确的含义。
  • 可行性:可以在当前环境条件下,通过有限次运算实现算法。
  • 输入输出:会有零个或多个输入,会有一个或多个输出。

「好」算法的标准

  • 正确性:能够满足具体问题的需求,在当前环境条件下运行正常,无语法错误。
  • 易读性:遵循标识符命名规则,简洁易懂,注释语句恰当适量,便于阅读。
  • 健壮性:对于非法的数据及操作,有较好的反应和处理能力。
  • 高效性:运行消耗的时间短。
  • 低存储性:运行需要的存储空间低。

二、不急,先来搞定不确定性

了解了算法的基础知识之后,尽管有坚定的态度想要学习算法,或者已经开始学习了,但是学习之旅可能没那么顺利,前路漫漫,总有一些沟沟壑壑。

于是我先扪心自问了几个问题:

  • 为什么对算法有逃避心理?
  • 如何爱上算法?
  • 怎么保持学习的热情和积极性?
  • 如何达成掌握算法的成就?
  • 学到的算法怎么应用到工作中?

先把不确定的因素找到,想办法逐个击破,才能收获想看到的风景。

三、算法之难,难于登泰山

先来会带第一个问题,之所以对算法有逃避心理,是因为看过、用过、接触过、尝试过、努力过,但是算法确实有点难。

再具体一点,算法的难点有以下几个方面:

  • 如何设计算法,使用什么算法策略比较好;
  • 如何确定算法的复杂性;
  • 复杂的算法,怎么学会它,理解它,掌握它;
  • 学习一段时间后,遇到新问题,仍然无从下手;
  • 怎么优化算法。

精通算法,肯定需要一段时间的研究,这个时间可以不是连续的,但是时间周期会比较长。这当中,会因为各种各样的原因,失去最初的学习热情。

四、发现算法之美,化兴趣为动力

都说兴趣是最好的老师。想要爱上算法,兴趣不可或缺。那么问题来了,对算法的兴趣如何培养?

我喜欢听故事,喜欢生活化的事物,这样可以让我更好理解,也更容易坚持学下去。

从日常生活出发

先来看几个生活化的场景。

场景一

假设你有一套空置的房子🏡,你想卖掉它。在咨询了几个房地产中介之后,你将粉刷一新的房子推向市场,然后静待有意者上门。每当一个看房人提出购买意向时,你基本上都要做决定,要么接受,要么拒绝。

但是,拒绝是有代价的,因为在下一个有意购买者上门之前,你需要再支付一周(甚至一个月)的抵押贷款,而且下一个购买者的报价未必更高。

那么什么时候才是卖房子🏡的最佳时机呢?

场景二

假设你今天开车去商场购物,商场的停车位,地上和地下都有,地下需要走的路更多一些,但是你打眼一看,地上停车位已经停了很多辆车,这个时候不确定是否还有车位可以让你停车。

如果选择了开入地上停车位,但是没有车位,需要将车辆从出口开出去重新从入口进入商场,这样一来会花费更多的时间。

那么你准备刚进入的时候选择地上停车位还是地下停车位?

场景三

假设有一个旅团,一共30个人,有男人、女人和孩童。大家参观到中午,选择去当地的特色小馆吃饭。这些人在这家饭馆一共花了500元,每个男人花30元,每个女人花20元,每个孩童花10元。

那么请问男人、女人和孩童各有几人?

算法之美

上面三个场景,多少都和日常生活有所关联。单纯靠猜,蒙对的几率很小。如果列个式子去解未知数,那么等式该怎么列呢?是不是兴趣上来了。

总结一下,我发现的算法之美。

化繁为简

日常无论是工作还是生活,有些场景可以借助算法,将复杂问题简单化。

比如买东西时怎么挑性价比高的商品、怎么用优惠组合可以让价格更低、出行时哪条路线更便捷等。

复杂一些的比如估算某件事的成本、某个规律性事件的数量、还有一些事件发生的概率以及什么概率下做决定比较多。

这些事,单纯靠想象,是比较难处理的,如果代入一些公式进行计算得到结果,怎么做选择就一目了然了。

降本提效

经过数学家欧拉的实验,以37%作为分界点,前面的时间用来观察,后面的时间用来作决策的一种方法。

这样一来卖房子和停车的问题,是不是就有解决思路了。

有规划成方圆

  • 在搜索省份和城市数据的时候,希望按照首字母进行分类展示。
  • 打开外卖APP,查看美食商家,可以按照距离筛选,也可以按照好评筛选。
  • 整理好装有100本书的书架和两个各有50本书的书架,哪个更费时?

这些问题,如果没有建立排序,想想数据量,就令人头皮发麻。

合理利用算法,可以为我们解决大数据量问题,也可以通过结果了解社会的本质。

所谓社会,就是我们维持的另外一种更重要、规模更大的秩序。

保持阶段性收获

我一般会保持下面这张图中的良性循环

渐入佳境的算法开发,分享一下学习心得_取值范围

学习中分阶段取得收获,每个阶段的收获可以鼓舞自己继续学习下去。

五、从热爱出发,贵在坚持

对事物保持长久的热爱,是一件比较困难的事。热情褪去,剩下的路该如何走?半途而废?差不多得了?

所以除了热爱,保持热情,坚持才能实现最初的目标。

如何做到坚持?

提高效率,缩短学习周期

周期太长,会因遗忘曲线,学习到后面的时候,已经忘记了前面的知识点。

避免拖拖拉拉的心态,以及拖延心理,缩短学习周期,有利于有始有终。

且提高学习效率,会有成就感,帮助提升学习积极性。

制定合理的目标规划

我一般是月度规划。因为平时要上班,可投入到学习中的时间,大部分是碎片化的时间。

所以一个新技术,用一个月的时间,完成从掌握到精通。学习周期不会因为过短导致学不到点子上,也不会因为过长导致有始无终。

我基本每隔两个月,会复盘一下之前计划的进度,做出适当的调整。

这个习惯已经坚持了三年多了,挺有收获的。(我之前也是拖拉的性子)

直面困难,迎难而上

回避是以不面对的方式来面对问题,它是一种消极的解决问题的方式。

像升级打怪,积累经验之后,相同的问题便不再是困难。

遇到新问题的时候,是会有些痛,但是这种痛是暂时的。「长痛不如短痛」,与其心怀忧虑,不如迎难而上。

所以,我在罗列出算法的难点之后,心里已经有了大致的学习规划,已经不是那个轻易被困难吓到的自己,除非这个困难不是一般的难。法子总比困难多。

养成记笔记的好习惯📒

「好记性不如烂笔头」。但是做笔记也有讲究,不要囫囵吞枣把所有的内容都记下来,这样效果不佳。

分享几个我日常写笔记的习惯。

新知识点

除了记录它是什么、能做什么、怎么用。最好把不理解的地方打上一些标记,回头翻阅笔记的时候,遇到记号就能产生学习联想。

解决方案

很多优秀的博主会分享知识点总结、解决方案。如果再看文章的过程中,遇到比较好的想法,要及时记录下来📝,后面如果实际开发中,遇到相同的问题,即便回忆不出具体的内容,但是最起码有模糊的记忆,可以找到当时记录的笔记。

此刻的叶一一十分感谢当初记笔记📒的叶一一

渐入佳境的算法开发,分享一下学习心得_算法之美_02

创意想法

创意灵感往往一闪而过,如果当时无法立刻实现,可以先把想法做一个简单的记录。有时间了,可以尝试实现它。

且创意想的多了,再需要的时候可以十分敏捷的想到实现方案。

阶段总结,为未来铺路

木桶定律,补短板

木桶定律:只木桶盛水的多少,并不取决于桶壁上最高的那块木块,而恰恰取决于桶壁上最短的那块。

有些短板是需要补长的,短板太明显,不利于个人成长。

以我自身举例,分享一下我曾经的短板和如何补长的:

  • 很多年前,我处理并发需求的能力很差,一旦任务多了,我就有点手忙脚乱。后来,我通过,提升开发效率、合理的开发设计以及开发时间分割,这三个方面的升级,现在面对并发需求游刃有余。
  • 很多年前,面对颠覆性的改动是很抗拒的,因为时间成本、代码重构成本、测试成本都很高,但是功能是确定的,只是修改时间早晚的事,越拖后,代码量增加,改动成功会递增。后来靠功能梳理和功能设计,颠覆性的改动也能很好的完成。

木桶逆定律,锻长板

木桶逆定律:扬长避短,让长处更长,把长板拼起来得到一个更长的巨大的木桶。

锻炼长处,提升技术能力,除了帮助成长,还可以成为自己的核心竞争力。

三省吾身

  • 近期是不是可以整理一波技术总结、实用功能总结、不错的解决问题方案;
  • 这段时间的规划,哪些还没有完成,为什么没有完成;
  • 如果没做规划,我是不是可以做点什么事情,比如写文章、读技术书籍、看技术文章、刷算法题库等。

六、知其然,知其所以然

怎样的学习方式,可以帮助实现掌握算法的心愿?

以写促学

一些写作图书中或教育理念中, 提倡「以写促学」。我是先自己有过经历才知道原来有这个理念。

我之前平均学习一门技术的周期很长,除了因为学习时间琐碎,最主要的是,吸收能力较弱。有些缺点和弱点,我就想着怎么能克服它们。

我是先从设计方案入手的,最初大型项目开发实际开发速度不如最初设想,有延期风险时都靠疯狂加班。后来我在领导的建议下,认真对待设计方案,从最初的写得不怎么样,到后面技术观点的输出。经历了一个从无到有的过程。

后来,我发现,对于稍微难一点的技术,通过写学习笔记、学习文章,克服抗拒的心理,梳理知识的重、难点。一旦坚持下来,收效有了明显上升。

对算法的学习,也是一边学,一边进行笔记输出、想法的输出。

以练代看

抛开刻板印象

有时候拿到算法数据或者文章翻看的时候,被铺面而来的文字给吓住了。想着这么多文字,自己能坚持读下去吗?烦躁心理一出,学习效率就会大打折扣。

抛开「文字多就晦涩难读」的刻板印象,其实一部分文字是算法的题干,一部分文字是算法分析,还有一部分文字是理论知识。有题干才会有解题,有分析才会有实现方案。

一上手就知有没有

对于算法题,尽量自己去真正的实现它。前期依样画葫芦,后期挡住答案,自己想实现方案。

练习几套下来,就有手感了,这种感觉是光凭阅读无法拥有的。

关于旅行团的算法问题

聊一下前面旅行团的问题

假设有一个旅团,一共30个人,有男人、女人和孩童。大家参观到中午,选择去当地的特色小馆吃饭。这些人在这家饭馆一共花了500元,每个男人花30元,每个女人花20元,每个孩童花10元。

那么请问男人、女人和孩童各有几人?

这道题的解题思路在我上篇文章《算法学习 | 与大师对话,翻阅大师手稿中的数学题》中,写的很详细,这里不再赘述。

算法延伸

提这个算法问题,其实我最想跟大家分享的是延伸部分,

我们换个角度再想想这个问题,前面的解题思路是通过确定x的取值范围,然后确定y和z的值。

如果通过确定y的取值范围,然后确定x和z的值,或者先确定z的取值范围,行不行?

有没有更好的降低时间复杂度的算法?

反复练习

古诗词中,很多都经过作者精雕细琢,反复推敲,有时为了一个字,都能想一晚上。这种反复琢磨、精益求精的精神还是值得借鉴的。

如下图是典型的练习曲线

渐入佳境的算法开发,分享一下学习心得_取值范围_03

  • 第一个曲线表示工作量对练习时间的关系;
  • 第二个曲线表示每次练习所需时间对练习次数的关系;
  • 第三个曲线表示每次练习的错误数对练习次数的关系。

算法可以采用刷题+方法总结的双行线,帮助锻炼解题思路、提升反应速度,以及减少出错数量。

七、学以致用,行以致远

就前端开发而言,我能想到的算法使用场景,排序问题、查找问题、最优问题、场景中的动画效果、抽奖概率、小游戏中、diff算法等等。

好似前端不怎么用算法,但是我罗列之后,发现用到的场景也不少。但是,似乎实际工作用不上,怎么检验自己的学习成果,学以致用呢?

  • 如果实际工作中没有使用机会,但是又想做练习的时候,可以到找一找这些场景,然后自己尝试去实现。
  • 工作中用到的现成的技术内容,像框架底层功能以及一些属性方法的底层实现也用到了算法,比如diff算法、数组的sort方法、对象与字符串的转换等。可以尝试着实现它们,加深对算法的应用。

八、写在文末

回顾一下全篇内容,从提问开始,以回答结尾。自问自答的方式,更有利于清楚根本问题在哪。

最后,做个简短的总结。

算法学习第一条建议:

知道算法是难的,但是难在哪,哪些难点可以克服,哪些难点不好克服。不妨先把困难点都列出来,逐条解决,问题便不再是问题。

算法学习第二条建议:

学习贵在坚持,但是坚持也是有窍门的。有技巧的坚持,才得到技术和热爱的双收获。

算法学习第三条建议:

以写代学、以练代看、反复练习,掌握算法,学以致用。