来自:知乎
链接:https://www.zhihu.com/question/31092580
C++ primer plus 过了一遍,今天做了 LeetCode 前几题,感觉有点吃力,得在草稿上写的明明白白才能理清思路。听说 LeetCode 只是很简单的算法。
迷路
我刚做Leetcode的时候,一道 easy 都要想半天,现在除了大多数的hard,一般都能通过。。。
大多数的 hard 都是特定领域的问题,如TCP的滑动窗口,编辑距离等。这些如果之前没有做过, 是很难独立完成的。我遇到问题的时候一般到 水中的鱼 找答案。这个博主是 facebook 的工程的,但有些题目他也没法立即想到答案或者最优解。所以别太灰心,好好做,会有收获的。
建议一次只针对一种题型进行训练,如数组、链表、二叉树、回溯、动态规划,这样效果会更好。
上个图说明我刷得很艰难。。
书籍方面《STL 源码剖析》 和 《算法技术手册》会帮你理解最常见的数据结构,查找和排序算法。
LeetCode题解:https://legacy.gitbook.com/book/siddontang/leetcode-solution/details
https://blog.csdn.net/linhuanmars/article/details/38468361
硅谷IT胖子
正常。
看网上大神,一堆一堆刷几个月就拳打狗,脚踢脸的,还秒了Uber和Airbnb。一堆Offer最差的Senior,最少的350K+。
可那是大神啊。幸存者偏差而已。
可能,人之前就是玩ACM的,LeetCode就像小儿科;可能,人之前就刷过好多次;可能,人就是万中无一的绝世高手。
可惜,你我不是。
那怎么办呢?不能洗智商洗技能树的话,就得接受现实:刷题,就是很痛苦很打击的过程,就是不断怀疑自己是不是适合搞CS这行的过程。
一遍一遍地刷刷刷,总结总结总结,实战实战实战。后面会有本质性的提高。
几道题,根本说明不了任何问题。
我个人觉得LeetCode的Easy和Medium是正常智商的人只要有信心和耐性,是绝对可以完全掌握的;Hard可能有50%需要较高的智商和一些指定的技能,剩下的也可以硬刷出来。
为什么这些公司考LeetCode原题?因为你能把Easy和Medium熬下来,甚至熬下来部分Hard,无论你的背景如何,你的自控能力、规划能力和坚持精神,已经足够在任何一个大公司做一个合格的工程师了。
路还远,慢慢走吧少年。现在868题。
【补充,好奇怪,这个简单回答怎么这么多赞】
我自己的经历,一开始刷LeetCode连最简单的都弄不好,反复磨才慢慢会的。而且我自己智商不太高,稍微复杂的东西就理解不了,所以弄着很累。记忆力还凑合,有些简单题慢慢开始就背下来,就是知道这么做,能写对代码,但不知道为什么这么做。
后来再刷时就开始碰Medium和Hard了,也是刷得一知半解,稍微变体就不会了,面试又是挂了一大片。
我当时也有点灰心。不过当时工作也不舒服,我过了一年又开始刷了,刷了4个月,大概500多道(算上之前刷过的),结果有一道Medium原题居然面试时还没做出来,可见实力还是一般。
但拿到心仪的Offer了,没白忙活。电话面试基本上不会挂。
我的体会是这东西熟能生巧,刷到后面不懂也懂了,就是个苦功夫、慢功夫。我学CS没什么天赋,但天性坚忍不容易放弃,其实就足够足够了。
====最后更新 Sep 26th,2018=====
几个月1.3K赞有点不理解,再多补充几句。
第一,我觉得要找到适合自己的学习方法。我记忆能力强,理解和抽象能力弱,属于顿悟型,所以就是靠速度快,类似的题(比如Graph类、DP类、Tree、LinkedList)来回拉锯,步骤是:
1、直接看答案,然后理解解答者的思路(甚至理解题意到底想干嘛),然后自己想,拿具体例子实验他的例子,理解为什么work,怎么work的,这段code的精髓在哪里。
2、然后自己写,不能抄,按照自己理解的思路写成自己的code,存起来。
3、重复1、2的过程,“刷”,因为不需要太多思考(个人弱项),并不累。重复几次下来,就很熟练了。
4、然后不断地实战,在实战中发现问题(比如没有真懂,变体不会解决等),回来再练;
5、最后达到争取能不看任何提示,给别人讲清楚这道题,一般就会终身不忘了;
第二,我觉得毅力远远比方法重要。没有或是不会方法,通过刷题是可以逐渐意识到自己的方法不对并且改进的;没有毅力,靠巧劲不是很好用。当然,最好方法也讲究一些,尤其是上了岁数的人。
我没有精研LC,可以说什么运行速度之类的我都没有看,因为反正是看别人的答案,肯定不可能是很糟糕的解法。
这种根本不精通,问题是一线公司面试中比如要求20分钟做一道Medium bug free,哪有时间扯细节?所以,神速、直奔主题、写code无bug是关键。以速度取胜。
最后,我LC并不强,跟大神比差太远太远了。但是我认为我的方法和努力是有一定成效的,因为我半路出家、懒笨、天资平平,尤其是抽象能力弱,按理说是不太适合这个行业的,但我依然找到了自己的出路,运气成分也不小。
面试不是看运气吗?我认为很看;面Google、FB全碰到Medium原题并不稀奇,但是你至少能做好Medium才是根本。假设每次面试有5%的幸运概率,那么每年面FLGUA一趟,连续面4年,就是20次机会。20次机会这5%幸运出现的概率是多少呢?我概率与统计不好,你们自己算吧。
所以说,幸运也总是眷顾那些肯刷题、肯去面试的人。放宽心态,在这行混,肯刷题,就是机会多多;不肯刷题,就是自己放弃了一片天地。
Aloys寒风
如果你刷着毫不费力,刷这个有个屁用呀。
IAMNOOB
leetcode的确是比较“简单”的算法,但你得把他放到正确的语境。如果你是一个以acm为目标的选手并且大量刷过poj之类的,那leetcode确实可以说是简单的,至少不用你去处理数据就省了很大的麻烦。
但如果你一不是科班出身二没有经过大量算法练习,比如我,leetcode题不会做绝对不是丢人的事而是再正常不过了。这就和做高数题一样你没练过接近的题型很多时候想破脑袋也未必能做出来。而且现在lc的难度越来越高,我现在还会时不时碰到短时间做不出来的medium题(我基本所有题都做过了),你可以想象我第一遍做leetcode的时候是多么痛苦。当然你可能觉得是我菜,但就我这水平刷400题都能在google match到组,可见做leetcode 如砍瓜切菜一般的人,比如stephan porchman那样的牲口还是极少数。所以只要你在做题的过程中能感受到自己的提高并且随着越做越多会的也越来越多就足够了。
最后,推荐你做每周的contest,这是一个不买会员做加锁题的方法。
贴张图,上周contest好不容易碰上简单题结果开始晚了要不可以进前20的...哎
胖君
太正常了,就算我正经计算机系毕业,算法课拿的A+,刚开始刷的时候也一脸懵逼,宛如一个智障。就上个月,脑抽以为自己可以了发了一个帖子,结果瞬间被各路竞赛小能手数学降维打击。现在坚持以二向箔形态回答这个问题,宝相庄严>,<
大家都见过哪些让你虎躯一震的代码?https://www.zhihu.com/question/287421003/answer/454958782
但我想说的是这个吃力只是暂时的。只要坚持刷一定能有进步。但这个刷是有方法论的,也是分流派的。前两天才写了一个回答,我觉得一种应该叫【兔系】刷法,另一种叫【龟系】刷法。兔系的大招叫”天马流星拳“,龟系的独门秘籍是”龟派气功“。懒得再码字了,搬运过来,大家随便看看。
大家都是如何刷 LeetCode 的?https://www.zhihu.com/question/280279208/answer/499663699
刷题的方法不是一尘不变的,根据目的的不同分为【兔系】和【龟系】两种。
【龟篇】
我自己是比较偏“龟系”的刷法【传送 >ciaoshen.com】。从一开始为了找工作,每天4,5题,到后来慢慢减少到1-2题,变成一种习惯,每天早上起来,喝两口咖啡先来一发。我个人比较信奉Peter Norvig的 “十年理论”。之前Dave Thomas提出的 ”Code Kata“ 也是类似的概念,核心理念就是 “刻意训练” 。现在刷leetcode就是我坚持的“刻意训练”的一部分。日常工作里调调参数,修修Bug,用用框架实际上达不到”刻意训练“的标准。像leetcode这样的OJ正好提供了这样一个”道场“不是很好吗。
我们有的时候过分注重了算法题的“算法意义”,而忽略了”工程意义“。题刷多了就知道,常用套路其实来来回回就那么几个。但明确了算法,能不能准确地实现,做到bug free又是另一回事。再进一步,数据结构用的合不合理,也会影响最终效率。代码写出来,别人好不好懂,又是另一个层面的要求。最后要参加面试,又必须在规定时间里完成,不但要写的快,代码还要干净,符合工程规范。
所以”龟系“刷法的精髓就是每个题目要做干净。所谓龟派气功,讲求一击必杀。不要满足于一种解法,各种解法都写一写。我现在accept了350+题,用了1000多种方法。平均每题2~3个Solution。基本每题都做到beats 90+%。
最好不要满足于accept,要追求最高效率。做一题就要杀死一题。leetcode不是给了运行时间的分布吗,基本上每个波峰都代表了一种特定复杂度的算法,中间的起伏体现的就是具体实现细节的差距。每次都要向最前面的波峰努力啊>.<。追逐最前一个波峰的过程不但锻炼算法,还锻炼数据结构,锻炼对库函数的熟悉程度。经常比较不同数据结构不同库函数的效率,时间久了能产生一种直觉,以后一出手就是最优选择。(小贴士:点开竖直的分布条,是可以看到对应代码的,对学习高手的解法很有帮助。)
但“龟系”不是说在一道题上耗死。越是龟系越要注意时间上要掌握好分寸,能解出来最好,解不出来也不要倔强。我觉得比较好的一个平衡点差不多是“一个小时”。如果一个小时还是解决不了可以点开右边Related Topics链接看提示。还是不能解决就看讨论区。
现在一年多坚持下来,最大的收获不是知道了多少算法套路,而是代码硬能力上的进步。之前经常会卡在一些实现细节的地方,现在只要整体方向确定下来业务逻辑捋清楚,具体实现编码反而是最轻松的工作。这就是为什么大厂面试要考算法。功底好的工程师才有精力腾出来考虑工程,产品方面的问题。在代码细节就耗死的工程师肯定不行。
【兔篇】
“兔系“更加符合”刷题“的说法,就是按标签刷,按公司刷。今天做binary tree就一下子做10,20题。有的人不喜欢太功利,觉得缺少思考的过程。其实完全可以打消这个顾虑。很多最后拿到FLAG offer的大神都这么干。而且过程之暴力令人发指。记得有个大神刷到第三遍,每天可以做80+题。拿到题根本不思考,直接在自带编辑框开始码,而且还基本做到bug free。
我也不知道他是不是在吹,但“兔系”的精髓就是要暴力,天马流星拳,大力出奇迹。有的人提倡”不要看答案“。这种观点我觉得是对的,像我自己就很少看答案。但作为兔系选手,讲求的就是要疯,不如一上来就看答案,就照着答案写。这个做法看起来不靠谱,其实它有内在的合理性:大部分算法都不是我们发明的。什么动态规划,二叉树,线段树,并查集,贪心算法,到后来所谓的不看答案自己做出来,其实都是在用固定套路。到最后你看那些acmer高手,看似思路很快,其实就是知道的套路比你多,而且不是多一点。所以既然明确了是为了找工作的目标,那就放下矜持,放下承见,拿到offer比什么都强,哪怕是以一种羊癫疯的姿势。
最后,刷题呢工具一定要用起来。比如我用Java刷,什么ant, gradle, junit, log4j, slf4j都用起来。可以省去很多搭环境,搭框架的时间,把精力都集中在解决算法上。leetcode虽然出了一个playground,但对vim支持还不太好。大的IDE又不爱用,现阶段我还是不得不自己开编辑器。这里给大家安利一个一键生成"Solution/Test"框架的小工具:
【leetcode-helper】
helloShen/leetcode-helper:https://github.com/helloShen/leetcode-helper
下载地址(最新v0.55):
【leetcode-helper-v0.55.tar】https://link.zhihu.com/?target=https%3A//github.com/helloShen/leetcode-helper/releases/download/v0.55/leetcode-helper-v0.55.tar
【leetcode-helper-v0.55.tar.gz】https://link.zhihu.com/?target=https%3A//github.com/helloShen/leetcode-helper/releases/download/v0.55/leetcode-helper-v0.55.tar.gz
【leetcode-helper-v0.55.zip】https://link.zhihu.com/?target=https%3A//github.com/helloShen/leetcode-helper/releases/download/v0.55/leetcode-helper-v0.55.zip
一行命令ant generate,生成支持Junit和log4j/slf4j的 Solution/Test/TestRunner 骨架类,
一行命令ant compile test,实现编译以及JUnit单元测试。
而且附带了一个leetcode常用数据结构包
com.ciaoshen.leetcode.util。 像常用的比如ListNode,TreeNode的基本实现都有了。
不需要安装,全都打包在一个jar
包里,放到classpath
底下就可以了。 最后把build.xml
和problem.properties
复制到工作目录,直接运行ant
即可。
现在每天早上拿着我的煎饼果子和咖啡,一键生成骨架,开编辑器就坐下来写算法,然后一键测试,提交。然后该干嘛干嘛。leetcode真的成了我的一种生活方式。不求名,不求利,但求无愧于心,干一行爱一行。
●编号804,输入编号直达本文
●输入m获取文章目录
人工智能与大数据技术
更多推荐《25个技术类公众微信》
涵盖:程序人生、算法与数据结构、黑客技术与网络安全、大数据技术、前端开发、Java、Python、Web开发、安卓开发、iOS开发、C/C++、.NET、Linux、数据库、运维等。