Friday, July 5, 2019

How to solve algorithms problems?

Here is the link of the article. 

二、刷题
刷题是大部分基础不好的同学最头疼的部分,也是最容易出现误区的部分。我总结了三大影响刷题效率的误区
  • 不管三七二十一,撸起袖子就刷题。只要我有决心,一定可以铁杵磨成针!
  • 刷题就是要看量大,只要刷满300题,Offer随我挑!
  • 刷题就是啃硬骨头,不会的题想一天也要想出来! vs 刷题就是背题,把题目背下来有一天自然会懂!
针对这三大误区,我有如下心得:

1. 刷题是以“数据结构和算法”相关知识为基础的
我看过很多地里的“刷题心得”,鼓吹勤奋至上论,号召一切找工作的人每天刷三题,坚持下去就有offer。我相信过,但实践效果很差。仔细思考之后,我认为是一种典型的不科学学习法。
我们学了这么多年习,都是先讲课再写作业。写作业从来都只是课堂知识的巩固。课堂知识是系统的,有层次递进的,相当于给房子打好地基和框架结构,而写作业是添砖加瓦。刷题就是写作业,对基本的数据结构和算法理解不深,只是知道个大概就刷题,实在是效率低。
我们可以先做一个大致的评估:请人在Leetcode所有分类tag里都随机抽取三道easy题(你并不知道题目类型),尝试一下:
  • 题目都能做出来么?
  • 如果做不出来,能看出来该用什么数据结构和算法么?
  • 如果看不出来,到discussion看一遍高票回答,能看懂么?看懂了能独立再写一遍么?
如果做到了第一层,可以直接刷题,在刷题中学习;做到了第二、三层,还应该再复习一遍Cracking the Coding Interview或者相关资料,再动手刷题;第三层也做不到,应该在学校里面选一门经典入门的数据结构与算法相关课程,认认真真上一遍,再来刷题。

事实上,我认为第二层及以下,都可以考虑再上一遍数据结构与算法相关课程,有一个坚实的基础。没有拿到A,都不能算是学通了这门课。. 1point3acres
2. 刷题和量没有任何必然关系
我直到找到正职,一共只刷了162道题,其中Easy 64,Medium 83,Hard 15。这当然是有运气成分在里面的,但也侧面说明数目不应该被拿来衡量刷题的掌握程度。我个人认为按照这样的原则刷题是效率最高的:
  • 刷一道题,会一道题。会一道题,是指这道题再出现在你面前千万次,你都能顺利的写出来,并且能够准确的分析时间复杂度和空间复杂度
  • 刷一道题,掌握一道题。掌握,不仅是能AC,而是要掌握最优解和经典解。比如一道题DP是最优解,你还应该用DFS写一遍,因为这也属于经典解。我身边有不止一个人面试的时候想写DP,被面试官要求用DFS,或者想用DFS,被面试官要求写DP。如果做题的时候没有融会贯通,这个时候就容易卡壳,追悔莫及。
  • 针对薄弱类别集训。我刚开始刷题的时候,就是打开Facebook tag,按频率题。刷了一定量之后,发现自己的Tree和DP特别垃圾,又将这两个tag下的题集训了一波,每一题都想:这个Tree题跟上一个Tree题都什么不同?为什么不能用相同的方法?坑都在哪里?之后遇到这两个类型,解题率就高了很多。
如果按照以上原则,每天啥也不干就刷题,也不可能刷很多道。我状态不好的时候一天只能刷三道题,状态好的时候也就能刷七、八道。虽然刷题量很可怜,但我能感觉到我的AC率在以很快的速度上升。

3. 刷题不能死磕,也不能硬背
对不起说了一句废话……这其实因人而异啦,我觉得最适合我的高效刷题流程是这样的
  • 看题后思考5~10分钟:用什么数据结构?用什么算法?空间和时间复杂度是多少?是不是最优解?
  • 如果有信心能写出最优解,或者觉得自己的解法值得一试:写题10分钟,debug最多5分钟
  • 如果写不出来或感觉没想清楚:立刻看Discussion里面的最优解和经典解:分析空间时间复杂度,为什么是最优解,为什么能想到用这样的数据结构和算法
  • 看完解答之后独立写一遍,不设时间,写到AC为止。期间如果想不清楚了,再重复上一步骤。
  • 写完还是觉得懵懵懂懂,加入一个list,准备二刷
另外,背题也是可以有很大作用的,但硬背的效率就太低了,我的背题方法如下. 1point3acres

  • 实在连解答也看不太懂,就照着最优解敲一遍,或者一步一步的过一遍代码
  • 在重要面试的前一天/几天疯狂背做过的tag题:不是背答案,是把每一题的思路和坑都过一遍,相当于在脑子里重新做一遍。这个方法对我来说相当管用。有些做过的题乍一看又不会了,但只要提醒一小点我就能想起来,那这“一小点”就是这题的关键,一定要记住。我面Facebook前一天背了一百五十多道做过的题,背到凌晨两点半,感觉比我刷半个月的题学得还多……毕竟温故知新嘛。
4.讲题比刷题更重要

光会做题不会讲,面试就容易出现“我的题目都做完了,也没有bug,但是没拿到offer”这样闻者伤心听者流泪的悲伤故事。讲题是有套路的,坚持以下这个流程
  • 拿到题,先问问题。没有问题也要憋出问题,比如数据类型,要不要考虑corner case,数据量多大,有没有时间要求blablabla
  • 分析题:一般是暴力解 + 最优解的分析顺序。先说你拿到这道题之后的直觉解法,说完之后再“灵光一现”,说出最佳解法。如果你不确定这题怎么做,这个过程就更加宝贵,你要充分和面试官讨论这道题,征求他的意见和建议,直到讨论出一个双方都满意的解法。
  • 写题:千万不要埋头苦写,每写完一个子模块都要跟面试官说一遍写了啥,为什么这么写。我曾经还用过一个小trick:有一道原题,之前刷题的时候有一个很细节的bug,我思考了很久才想清楚为什么要这样处理。写题的时候,我想像面试官展示这个细节的精妙之处,就故意写了bug,写完这个小模块之后假装沉思一下,再一副恍然大悟的样子跟面试官说“我突然发现这样处理虽然看起来是对的,但其实有个corner case……”。面试官其实根本就没注意到这有个bug,我解释了一会儿,还举了例子,他才发现这个处理的有趣之处。我相信这样他对我的印象更深刻了。
  • 主动跑test case:写完之后,不要让面试官开口,而是主动说“那么现在我写完了,让我们来跑几个test cases,看看这个算法对不对”,面试官好感度立刻增加。

No comments:

Post a Comment