与力扣(Leetcode)相处的几个月
做完今天的练习,发现自己已经“解答了99道问题(其实有水分)”,于是截个图写一篇日志作为纪念。
我本科不是学习计算机的,不过对于这个专业一直都有点向往。于是在某个所有人都困在家里的春天,我开始了自学。我跟随着一个叫做OSSU的课程表,从简单的Python入门开始学习,然后学习OOP编程,网络,编译,算法,一直到完成了一个全栈项目。也许以后我会专门为这些学习写相应的日志。
我跟随的算法课程是斯坦福的CS161. 因为完全是菜鸟的缘故,我的学习流程是:听了几节课,获取了所有的课本,独自阅读完这些课本,然后认为自己已经“明白了算法的大意”。现在回想一下这是很糟糕的策略:更好的策略就是每当学习一种算法的时候,一定要用熟悉的语言一次又一次的重复把代码打出来,增进自己的理解。当时我学习算法时还没有做那个全栈的项目,所以任何语言都很不擅长,因而也完全没有手打代码增进理解的机会。
完成全栈的项目之后,我对于JavaScript这个语言的使用稍微感觉自信了一些。我开始留意是否有简单的工作/实习机会。随后我在网络上得知了Leetcode这个可以学习算法,准备面试的网站。那时好像是2021年的11月底。注册后,这个网站“复杂”的外观立即震撼了我。我感到自己并没有完全准备好开始练习。所以又多花了些时间(偷懒)才开始正式的使用Leetcode。
新年的开始总是让人抱有期望。于是我开始了探索:随便做一点练习,发现自己对于题目完全没有头绪!在新年的假期里,我大概坚持了7天就放弃了。
两个月后,看完了另外两门课的教科书,我又重新拾起了Leetcode. 因为对于寻找实习有兴趣,所以我决定从“热门面试问题”开始练习。我搜索了很多前辈的经验,发现几乎所有人的开始都是“非常迷茫,完全不会”的状态。有的人建议先自己做题,但10分钟内没有头绪就看答案,然后逐渐自己分析,并且一遍又一遍的把好的答案打会。我的第二次尝试尽可能的遵循了这个原则,但是很遗憾,因为每一天都无法独立做出题目,这个学习过程逐渐变成了对于题目的死记硬背。这个过程一点也不快乐,也很消耗我的耐心,所以坚持了大约三周后,我又一次放弃了。
之后几个月,我将精力投入了其他的事项,一直都没有再登陆上力扣,直到自己经历一次很重大的失望,心情糟糕透顶,完全没有了前进的动力之时。契机是这样的,沉浸于偷懒摸鱼的我读了一本叫做“福格行为模型”的书,它认为:
- 如果要养成一个习惯,先将习惯分解成一个最最微小的行为(如果运动是想养成的习惯,那么最微小的行为是每天做一个俯卧撑)
- 将这个微小行为放到每天的固定时间 (比如说早起刷牙后)
- 每天完成这个微小行为,并且及时奖励自己 (比如说吃一顿丰盛的早餐,或者在酸奶里多加一些梅子)
我感觉这并不是很难做到的事。为了验证这个理论,我选择了养成 “刷Leetcode” 这个习惯。高难度,高回报,即使失败了也没有什么关系——反正我已经失败很多次了。于是我制定了自己的计划:
- 每天只做一道题,而且是简单/中等难度
- 每天早上喝完咖啡之后,就开始做题,做完就进行正常的生活
- 每天做完题后,鼓励自己 (也许吃点甜品)
于是八月就坚持下来大概二十天。也许是“只做一道题”成为了我的心理后盾,这一次练习之中感到的痛苦少了一些。也许是生活中的其他的悲伤让我有了“通过学习来逃避”的想法。很遗憾,我仍然没有摆脱“学习-满意-遗忘-失望”这个过程。
时间来到九月,我意外的发现每天能否登陆上Leetcode变得不太稳定了! 于是我错过了很多登陆和练习的机会。我的情绪变得非常焦躁,同时也为又一次的失败感到遗憾。
但是八月和九月之中我的收获就是停止了直接刷“最热面试问题”,而是开始使用Leetcode explore进行学习。它是官方的分专题的学习资料。我还使用其他教科书配合力扣专题一起阅读。我使用Notion做笔记,将所有的材料和自己的进度详细标注好。我终于可以弥补自己之前学习算法的遗憾啦。于是,使用着不稳定的网络,我磕磕绊绊的学习递归,二叉树,回溯法,动态规划等。
二叉树和递归都是让我头疼的项目。我一边练习一边翻看着《剑指offer 分类练习》这本书中的解答。作者说二叉树的三种DFS遍历方式的递归解答和迭代解答都应该烂熟于心。而当时的我就连最简单的递归都写不好。于是我实施了“最笨的办法”:每天手打一遍这6种遍历方式。看着答案打,然后提交,然后看着代表当天的小格子变得非常明亮。
在这个过程中,我将leetcode的cn版本作为了上不去网时的替代品。于是,我又多拥有了一些发亮的小格子。我继续手打二叉树的各种遍历。
有一天,我无意中更改了自己的某项网络设定,我惊讶的发现Leetcode又可以稳定的访问了。这种山穷水复柳暗花明的感觉像极了去年我学习全栈课程的时候。那时候我的一个系统设定没有设置好,于是好几天枯坐在电脑前都没有办法取得任何进展。最后是在stackoverflow搜索了很久,才找到好用的答案。于是我眼泪汪汪的发现自己制作多日的网页加载了出来(其实是一个小破网页而已),心里暗暗感谢宇宙给了我回应,在我放弃之前让我问了正确的问题,得到了能用的答案。
读者读到这里,会不会觉得我的算法学习一定也“开窍”了?就像文学作品里的主人公一样,经历痛苦的练习之后就一通百通了吗?
有,也没有。
我对“递归”的理解确实随着一次又一次手打代码而增加了。但现在的我还没有能独立解出困难问题的能力。图中我的两道困难问题,都是自己看了答案之后手打提交的,其实并不算我学会的东西。
但是对于某些简单题,我真的进步了。前几天为了树立自信心,我找了一道简单难度的题,然后自己做完提交,我的解法居然非常快,超过了95%的人群。于是我发布了自己的解法在评论区——这是一种新的体验。
在昨晚,我被一道回溯法的问题难倒(是老朋友,之前某次放弃的元凶)。我没有按照回溯法的套路来解出,反而自己使用了一种笨笨的办法,居然也提交成功了。于是我再次发布了自己的解法(虽然没什么人气)。
这两件事给了我一个启发:螺旋式的上升。或者说,有时我的进步并不像我期望的那样,但是我又确实感到自己有了一点进步。而这就是这几个月痛苦,迷茫,每天做枯燥的练习,对着书本和屏幕冥思苦想,白了好几根头发之后的所得。
我承认自己对于“工程师”的期望还是比较幼稚的——希望能和有创造力的大家一起制造一个东西出来,希望大家认可我是个聪明又努力的人,希望能远程在小动物的陪伴下工作。我缺乏经验。但是这几个月的经历给了我一点底气:我已经攀爬了一点金字塔,经历了起落,并且我还没有放弃。记得《摩登家庭》里菲尔修好了家里的洗衣机,他感到特别自信,就决定与杰合伙承包一块地修建他的邓菲塔。结果那地挖开一点点就破坏了燃气管道,修建大楼是完全不可能的。经过深思后,菲尔和杰决定将此处改为停车场。那停车场居然很受欢迎。
我想我也有一点自信了,无论未来是否会从事CS相关的工作。也许生活也会给我一些这样的惊喜和指引吧。
喜欢我的作品吗?别忘了给予支持与赞赏,让我知道在创作的路上有你陪伴,一起延续这份热忱!