我和这位网友的这些描述十分相似,我困惑,迷茫。希望网友能给出自己好的学习方法,感谢。
从刚上大学在课堂上听老师讲解,到后来自学,反复学等种种失败经历给了我当头棒喝。我这样的小渣渣还真是难以捧本书看一看就能学懂。还真得特殊准备一套方法来学习它。借助知乎,网上大神,ACMer的经验分享,我自己总结了一个入门的学习方法,让我快乐且热情的坚持下来了对数据结构与算法的学习。(
仅针对初学者的入门级学习,大神们请绕过,拜拜么么哒)
好,剩下来像我一样的阿渣们,让我们先来痛快的分(tu)析(cao)下为啥这东西难学:
1. 抽象,数学知识多,大多数书籍有很多数学证明,很枯燥,爱掉头发。
2. 反馈差。比如学完了“快速排序”也就学完了,没什么事做,也没觉得自己厉害多少。但是要是学习下cocos2d-x,过几天自己都能写小游戏了。学了难以分分钟高能还真就难以坚持了。没错,学习这事我就是这么投机这么功利。
3. 孤立的知识点都很难有什么作为,只有理解+融汇+贯通才能显威力。
4. 没有好“老师”。搜索下“如何学习雅思&托福”,各种高能大法学习小组培训机构怒刷一脸屏。
好了,吐槽完毕,以下是干货:
1.先来本入门级的好书
<img src="https://i-blog.csdnimg.cn/blog_migrate/1b2ea3470bef7650faf3eb1dc9801eff.png" data-rawwidth="334" data-rawheight="468" class="content_image" width="334">我把里面的代码全打了一遍,整不懂就一点点在草纸上演示,还整不懂的就死记硬背了下来,说不定哪天就想通了。学起来很慢,但是效果不错。谁让我笨呢。(现在没事抽风还要默写一下AVL树的c实现,也是病没好)
我把里面的代码全打了一遍,整不懂就一点点在草纸上演示,还整不懂的就死记硬背了下来,说不定哪天就想通了。学起来很慢,但是效果不错。谁让我笨呢。(现在没事抽风还要默写一下AVL树的c实现,也是病没好)
2. 可视化
刚开始我就按照1这么学,学一周就学不动了,太高估自己的能力,又冒充不下去学霸了。这知识尼玛这么抽象。之后发现了一个可视化工具(很多大神都推荐过啦)
什么冒泡插入快速排序一演示,小动画一播放分分钟我就都整明白了,一低头那些小代码也就都被我看穿看穿了。来一把倚天剑屠龙刀我也能混个山大王。
<img src="https://i-blog.csdnimg.cn/blog_migrate/5877538143d8df0f0598a9dd333a1785.png" data-rawwidth="964" data-rawheight="478" class="origin_image zh-lightbox-thumb" width="964" data-original="https://pic3.zhimg.com/71b69c54bff755bb0e8aa93ce5da5f3e_r.jpg">(图是二叉堆的演示)
(图是二叉堆的演示)
一可视化之后你会发现很多抽象的数据结构在脑海中有了样子。我也说不太明白那种感觉,就好像你在一个姑娘/小伙子身上看到了爱情的样子。
3. 实践&&默写
就这样你愉快的学会了“左式堆”,那你不得赶紧找个倒霉蛋在它身上练练你的新招式。好了,百度“ACM + 左式堆”发现杭电oj上1512 Monkey King这题就可以用得到我们的新招式。刷它一发。 但是要注意,我们不是为了成为ACMer,不为了刷题,而是拿一个实在的题去练习我们刚学的数据结构。所以能否ac真的不重要,写完的程序能把题目里提供的最简单的测试例子通过就行。(就这道题其实还会用到并查集,其实还有很多乱七八糟需要注意,可烦。)所以,只做简单的,你觉得有意思的,千万别纠缠某一道题。 结果不重要,练习下所学知识的是如何使用的就好了。这些实践题也不局限在HDOJ上,Poj,LeetCode等简单适合的都可以做一做。(因为我学的时候一直在杭电上练习,所以就拿HDOJ上的题举例子了)
只做简单的,结果正确与否不重要。没有合适的题,就默写遍书中实现!!!
只做简单的,结果正确与否不重要。没有合适的题,就默写遍书中实现!!!
只做简单的,结果正确与否不重要。没有合适的题,就默写遍书中实现!!!
<img src="https://i-blog.csdnimg.cn/blog_migrate/a2f00022c1aabe399765feff1441e438.png" data-rawwidth="1946" data-rawheight="406" class="origin_image zh-lightbox-thumb" width="1946" data-original="https://pic2.zhimg.com/c7b900973903d5b4f5c278d9be3c0f75_r.jpg">(图是Monkey king问题的描述,是不是比较好玩,一群蠢猴。)
(图是Monkey king问题的描述,是不是比较好玩,一群蠢猴。)
/*****这里做一个补充,我给大家一个具体的例子。比如学完了不相交集(并查集),你会发现HDOJ上1232,1213这两道简单题你一下子就会做了,但是2818这种变形题就需要你对路径压缩有很好的理解的基础上才能想明白。再墨迹一遍:做ACM题只要保证 所使用到的数据结构是我们自己实现的就好,至于解题思路,输入输出,特殊情况甚至结果都不重要,我很多时候都是上网找的现成题解,自己也有改编原题的输入数据(全变成int方便读取)。所以对于不重要的部分,要尽量忽略去节约时间。 越快往后学越好,学的不扎实可以反复学,比没学强。*****/
想练习哪个知识点的习题可以参见:(再次重申我们不是ACMer,没必要完全做对!!)
好了,总结起来就是 对于每一个知识点,我们用 学理论+ 可视化+ 编程实践or默写相结合的方式 一个知识点一步地踏实前进。当我们这样把经典的数据结构与算法了然于心之后,就会发现以后遇到多么高级多么复杂的结构与思想都不过是这些基础的变形或升级。
但是到这里我们真的就只是入门,真的就只是入门,真的就只是入门。还是要去从基础开始学习算法,学习时间复杂度分析,学习诸多优秀的算法思想,等等等。进而走进算法分析与设计这浩瀚的知识海中,但有了入门基础,你会发现以前看不懂的东西现在变熟悉了,虽然它们还是那么难。这时候我们才可以说修行看个人了。
所以我在这之后就愉快的重新认真地撸《算法导论》去了。可以参见我另外一个回答: 你是如何坚持读完《算法导论》这本书的? - 孟祥丰的回答。撸完如果觉得不够可以继续撸其它一些算法书籍,详情参见大神文章: 我的算法学习之路
虽然我还是觉得自己很渣很菜,但想想没有昨天那么渣了,就会很开心。
好,剩下来像我一样的阿渣们,让我们先来痛快的分(tu)析(cao)下为啥这东西难学:
1. 抽象,数学知识多,大多数书籍有很多数学证明,很枯燥,爱掉头发。
2. 反馈差。比如学完了“快速排序”也就学完了,没什么事做,也没觉得自己厉害多少。但是要是学习下cocos2d-x,过几天自己都能写小游戏了。学了难以分分钟高能还真就难以坚持了。没错,学习这事我就是这么投机这么功利。
3. 孤立的知识点都很难有什么作为,只有理解+融汇+贯通才能显威力。
4. 没有好“老师”。搜索下“如何学习雅思&托福”,各种高能大法学习小组培训机构怒刷一脸屏。
好了,吐槽完毕,以下是干货:
1.先来本入门级的好书
<img src="https://i-blog.csdnimg.cn/blog_migrate/1b2ea3470bef7650faf3eb1dc9801eff.png" data-rawwidth="334" data-rawheight="468" class="content_image" width="334">我把里面的代码全打了一遍,整不懂就一点点在草纸上演示,还整不懂的就死记硬背了下来,说不定哪天就想通了。学起来很慢,但是效果不错。谁让我笨呢。(现在没事抽风还要默写一下AVL树的c实现,也是病没好)
![](https://i-blog.csdnimg.cn/blog_migrate/1b2ea3470bef7650faf3eb1dc9801eff.png)
2. 可视化
刚开始我就按照1这么学,学一周就学不动了,太高估自己的能力,又冒充不下去学霸了。这知识尼玛这么抽象。之后发现了一个可视化工具(很多大神都推荐过啦)
http://visualgo.net
<img src="https://i-blog.csdnimg.cn/blog_migrate/5877538143d8df0f0598a9dd333a1785.png" data-rawwidth="964" data-rawheight="478" class="origin_image zh-lightbox-thumb" width="964" data-original="https://pic3.zhimg.com/71b69c54bff755bb0e8aa93ce5da5f3e_r.jpg">(图是二叉堆的演示)
![](https://i-blog.csdnimg.cn/blog_migrate/5877538143d8df0f0598a9dd333a1785.png)
一可视化之后你会发现很多抽象的数据结构在脑海中有了样子。我也说不太明白那种感觉,就好像你在一个姑娘/小伙子身上看到了爱情的样子。
3. 实践&&默写
就这样你愉快的学会了“左式堆”,那你不得赶紧找个倒霉蛋在它身上练练你的新招式。好了,百度“ACM + 左式堆”发现杭电oj上1512 Monkey King这题就可以用得到我们的新招式。刷它一发。 但是要注意,我们不是为了成为ACMer,不为了刷题,而是拿一个实在的题去练习我们刚学的数据结构。所以能否ac真的不重要,写完的程序能把题目里提供的最简单的测试例子通过就行。(就这道题其实还会用到并查集,其实还有很多乱七八糟需要注意,可烦。)所以,只做简单的,你觉得有意思的,千万别纠缠某一道题。 结果不重要,练习下所学知识的是如何使用的就好了。这些实践题也不局限在HDOJ上,Poj,LeetCode等简单适合的都可以做一做。(因为我学的时候一直在杭电上练习,所以就拿HDOJ上的题举例子了)
只做简单的,结果正确与否不重要。没有合适的题,就默写遍书中实现!!!
只做简单的,结果正确与否不重要。没有合适的题,就默写遍书中实现!!!
只做简单的,结果正确与否不重要。没有合适的题,就默写遍书中实现!!!
<img src="https://i-blog.csdnimg.cn/blog_migrate/a2f00022c1aabe399765feff1441e438.png" data-rawwidth="1946" data-rawheight="406" class="origin_image zh-lightbox-thumb" width="1946" data-original="https://pic2.zhimg.com/c7b900973903d5b4f5c278d9be3c0f75_r.jpg">(图是Monkey king问题的描述,是不是比较好玩,一群蠢猴。)
![](https://i-blog.csdnimg.cn/blog_migrate/a2f00022c1aabe399765feff1441e438.png)
/*****这里做一个补充,我给大家一个具体的例子。比如学完了不相交集(并查集),你会发现HDOJ上1232,1213这两道简单题你一下子就会做了,但是2818这种变形题就需要你对路径压缩有很好的理解的基础上才能想明白。再墨迹一遍:做ACM题只要保证 所使用到的数据结构是我们自己实现的就好,至于解题思路,输入输出,特殊情况甚至结果都不重要,我很多时候都是上网找的现成题解,自己也有改编原题的输入数据(全变成int方便读取)。所以对于不重要的部分,要尽量忽略去节约时间。 越快往后学越好,学的不扎实可以反复学,比没学强。*****/
想练习哪个知识点的习题可以参见:(再次重申我们不是ACMer,没必要完全做对!!)
http://www.acmerblog.com
好了,总结起来就是 对于每一个知识点,我们用 学理论+ 可视化+ 编程实践or默写相结合的方式 一个知识点一步地踏实前进。当我们这样把经典的数据结构与算法了然于心之后,就会发现以后遇到多么高级多么复杂的结构与思想都不过是这些基础的变形或升级。
但是到这里我们真的就只是入门,真的就只是入门,真的就只是入门。还是要去从基础开始学习算法,学习时间复杂度分析,学习诸多优秀的算法思想,等等等。进而走进算法分析与设计这浩瀚的知识海中,但有了入门基础,你会发现以前看不懂的东西现在变熟悉了,虽然它们还是那么难。这时候我们才可以说修行看个人了。
所以我在这之后就愉快的重新认真地撸《算法导论》去了。可以参见我另外一个回答: 你是如何坚持读完《算法导论》这本书的? - 孟祥丰的回答。撸完如果觉得不够可以继续撸其它一些算法书籍,详情参见大神文章: 我的算法学习之路
虽然我还是觉得自己很渣很菜,但想想没有昨天那么渣了,就会很开心。
再来看看其他网友的看法:
The key to a solid foundation in data structures and algorithms is not an exhaustive survey of every conceivable data structure and its subforms, with memorization of each's Big-O value and amortized cost. Such knowledge is great and impressive if you've got it, but you will rarely need it. For better or worse, your career will likely never require you to implement a red-black tree node removal algorithm. But you ought be able—with complete ease!—to identify when a binary search tree is a useful solution to a problem, because you will often need that skill.
打好数据结构和算法基础的关键并不在于对于所有数据结构的细致的了解,不是记住每一个大O值或者摊余成本..((@_@;)? [不懂]).
如果这些知识你都掌握了,当然很棒并且可以给人留下很深的印象,但是你基本上用不着啊!
你的职业生涯中或许永远都不会要求你实现一个红黑树删除节点的算法.但是!你必须有能力而且手起刀落轻轻松松的识别出什么时候使用二叉树更简单更有效, 因为你十 分需要这样的技巧.
So stop trying to memorize everything. Instead, start with the basics and learn to do two things:所以,不要试图记住所有的东西.而是从基础开始,做两件事:
- Visualize the data structure. Intuitively understand what the data structurelooks like, what itfeels like to use it, and how it is structured both in the abstract and physically in your computer's memory. This is the single most important thing you can do, and it is useful from the simplest queues and stacks up through the most complicated self-balancing tree. Draw it, visualize it in your head, whatever you need to do: Understand the structure intuitively.
- Learn when and how to use different data structures and their algorithms in your own code. This is harder as a student, as the problem assignments you'll work through just won't impart this knowledge. That's fine. Realize you won't master data structures until you are working on a real-world problem and discover that a hash is the solution to your performance woes. But even as a student you should focus on learning not the minutia details but the practicalities: When do you want a hash? When do you want a tree? When is a min-heap the right solution?
- 第一件事. 把数据结构图形化,视觉化.(突然想起来我高中竞赛老师说的一句话:数形结合千般好,一旦不做万事休啊! 就是要画图! )在直觉上感受一个数据结构是什么样子的.使用它是什么感觉,抽象上和具体实现上是什么样子的.这就是最重要的事情.并且无论是对于简单的队列,栈还是天杀的平衡树都很重要而且有效.把数据结构画出来,在你的脑袋瓜里面就能想象出来,总之,你需要做的就是,直观的去了解这些数据结构.
- 第二件事.学习什么时候用什么样的数据结构和算法.对于学生来说这很难,而且你要做作业的时候老师也没告诉你们这该怎么办.╮( ̄▽ ̄")╭ 不过没关系. 你要认识到当你真正处理到现实问题的时候或许你才能掌握某些数据结构,比如哈希表.但是即使是个学生,你也应该知道数据结构的实用性:什么时候你需要个哈希表,什么时候你需要个树,什么时候你需要个堆? 而不是一开始就陷入到追求细节中去.
One of the questions I ask in Google engineering interviews has a binary search tree as a potential solution (among others). Good candidates can arrive at the binary search tree as the right path in a few minutes, and then take 10-15 minutes working through the rest of the problem and the other roadblocks I toss out. But occasionally I get a candidate who intuitively understands trees and can visualize the problem I'm presenting. They might stumble on the exact algorithmic complexity of some operation, but they can respond to roadblocks without pause because they can visualize the tree. They get it.
我在google面试的时候,我经常会问一个可以由二叉树搜索解决的问题. 好的应聘者可以几分钟内就可以想到用二叉树来解决,而且对于我的其他问题也差不多10-15分钟就 可以解决.当然,偶尔会有一个应聘者,他能直观的认识树这种结构,而且可以把我的问题形象化,图形化的描述出来.当然他或许对于某些操作的时间复杂度不甚了解,但是对于 问题他却可以立马回应,因为他们脑袋里就有这样的树结构啊~所以他也能拿到工作啊.
但我想说的是,对于IT同学来说,学习算法的真正意义与方法。虽然现在越来越多的工具,库已经完全封装了很多底层实现,让更多的程序员是傻瓜式的使用即可,这一方面确实促进了开发效率,但这并不能代表我们不需要去了解算法本身的作用。只有知道某一个组件真正的实现原理(很多时候就会用到算法),才能明白其真正的应用场景,在哪种情况下合适,因为任何算法都有优缺点,都会有一个最佳应用场景和最坏应用场景。
特别是对于后端开发,涉及到高并发,大数据处理相关的开发的人来说,算法相当重要,特别是对于性能要求极佳的场景。如果不明白,虽然你能够实现功能,但你永远无法知道如何进行性能调优,无法真正将项目产品化。
如何实好算法,其实是多看,多练,多写,最为重要的,就是了解算法的本质,了解的办法无他,练习。
特别是对于后端开发,涉及到高并发,大数据处理相关的开发的人来说,算法相当重要,特别是对于性能要求极佳的场景。如果不明白,虽然你能够实现功能,但你永远无法知道如何进行性能调优,无法真正将项目产品化。
如何实好算法,其实是多看,多练,多写,最为重要的,就是了解算法的本质,了解的办法无他,练习。