算法漫游指北(第一篇):什么是数据结构与算法?为什么要学习数据结构与算法?怎么学习数据结构与算法?

一、什么是数据结构?什么是算法?

什么是数据结构?

Sartaj Sahni在他的《数据结构、算法与应用》一书中称:“数据结构是数据对象,以及存在于该对象的实例合组成实例的数据元素之间的各种联系。这些联系可以通过定义相关的函数来给出。”他将数据对象(data object)定义为“一个数据对象是实例或值的集合”。

Clifford A.Shaffer在《数据结构与算法分析》一书中的定义是:“数据结构是 ADT(抽象数据类型Abstract Data Type) 的物理实现。”

大话数据结构:数据结构是相互之间存在一种或多种特定关系的数据元素的集合。

mooc-陈越:数据结构包括数据对象集以及它们在计算机中的组织方式,即它们的逻辑结构和物理存储结构,同时还包括与数据对象集相关的操作集,以及实现这些操作的最高效的算法。

个人:就是把图书馆中的书转化为一些字符数据存入电脑中,以及对这些数据对象集的操作。如找书,摆放放书等。

什么是算法?

还是图书馆的例子,如果一本一本找累死人,要是有个索引,先找哪一类这样会快很多。如何查找其实就是算法。

算法是解决问题步骤的有限集合,通常用某一种计算机语言进行伪码描述。通常用时间复杂度和空间复杂度来衡量算法的优劣。

算法的五大特征:输入、输出、有穷性、确定性、可行性。

输入:零个或多个输入。

输出:一个或多个输出。

有穷性:有限步骤后在可接受时间内完成。

确定性:每个步骤都有确定含义,无二义性。

可行性:每一步都是可行的。

算法设计要求:正确性、可读性、健壮性、时间效率高和存储低。

正确性:有输入输出,无二义性,有正确答案。

可读性:方便阅读。

健壮性:输入不合法能处理

时间效率高和存储低:时间空间复杂度越低越好。

这就是数据结构和算法。

数据结构有哪些?

 

数据结构可以简单分为:排序、链表、列表、生成树、树、图、栈、哈希

 

抽象数据类型可以分为:栈、队列、集合、映射

数据结构中英文对照

Data Structure
​
Array                      数组
Stack / Queue              栈/队列
PriorityQueue              优先队列     
LinkedList                 链表
Tree / Binary Search Tree  树/二叉搜索树
HashTable                  哈希表
Disjoint Set               并查集 
Trie                       字典树(单词查找树)
BloomFilter                布隆过滤器
LRU Cache                  LRU缓存
​

  

 

算法有哪些?

1、十大排序算法

  • 简单排序:插入排序、选择排序、冒泡排序(必学)

  • 分治排序:快速排序、归并排序(必学,快速排序还要关注中轴的选取方式)

  • 分配排序:桶排序、基数排序

  • 树状排序:堆排序(必学)

  • 其他:计数排序(必学)、希尔排序

2、图论算法

  • 图的表示:邻接矩阵和邻接表

  • 遍历算法:深度搜索和广度搜索(必学)

  • 最短路径算法:Floyd,Dijkstra(必学)

  • 最小生成树算法:Prim,Kruskal(必学)

  • 实际常用算法:关键路径、拓扑排序(原理与应用)

  • 二分图匹配:配对、匈牙利算法(原理与应用)

  • 拓展:中心性算法、社区发现算法(原理与应用)

 

3、搜索与回溯算法

  • 贪心算法(必学)

  • 启发式搜索算法:A*寻路算法(了解)

  • 地图着色算法、N 皇后问题、最优加工顺序

  • 旅行商问题

 

4、动态规划

  • 树形DP:01背包问题

  • 线性DP:最长公共子序列、最长公共子串

  • 区间DP:矩阵最大值(和以及积)

  • 数位DP:数字游戏

  • 状态压缩DP:旅行商

 

5、字符匹配算法

  • 正则表达式

  • 模式匹配:KMP、Boyer-Moore

 

6、流相关算法

  • 最大流:最短增广路、Dinic 算法

  • 最大流最小割:最大收益问题、方格取数问题

  • 最小费用最大流:最小费用路、消遣

 

部分算法中英文对照


Greedy                            贪心算法
Recursion/Backtrace               递归算法/回溯算法
Traversal                         遍历算法
Breadth-first/Depth-first search  广度优先搜索/深度优先搜索
Divide and Conquer                分而治之法简称分治法
Dynamic Programming               动态规划
Graph                             图
Pre-order/In-order/Post-order traversal   前序/中序/后序遍历
Binary Search                     二分查找
 

  

 

 

二、为什么要学习数据结构与算法?

此处省略一万字...

 

三、怎么学数据结构与算法?

 

1、刻意练习:

指的是针对一个模块的知识点,刻意的进行练习,并且要练习自己有缺陷跟弱点的地方,特别是让自己有不舒服、不爽、枯燥的感觉。比如生活中的例子:乒乓球、台球、游戏等等。

 

2、反馈:

  • 反馈要即时,分如下两种:

  • 主动型反馈:指的是找比自己做得更好的人,他们是如何做的。编程的话,就是阅读大牛的源代码:github, leetcode;还有第一视角的直播。

  • 被动型反馈:指的是高手给你的指点。比如:code review

 

核心概括一下:

  • 把学习算法和数据结构这个整体进行切分,可以看到是上面这么多种类,根据这些种类来进行学习。

  • 刻意的练习自己的薄弱环节。

  • 看大量的高手代码,刷大量的leetcode题目。

  • 解题的时候要实现所有的方法,比较算法时间和空间复杂度。

 

3、算法面试面试时的切题四件套

  • Clarification(明确)

先把题目弄明白,看看有没有什么比较阴险的地方,边界啊范围啊之类的

  • Possible solutions (可能的解决方案)

    • compare(time/space)(比较时间复杂度和空间复杂度)

    • optimal(加强)

    找到尽可能多的解,找到最佳解,多问,多思考

     

  • Coding (多写)

    边学边练,适度刷题,用编辑器或者IDE在本地敲代码

  • Test cases (测试案例)

看Solutions和Discussions板块学习别人的代码

 

知识需要沉淀,不要想试图一下子掌握所有,不要一下子学习太多,然后还学的不咋地,最后放弃了。

 

总结一下就是:我们遇到什么困难,也不要怕,微笑着面对它,消除恐惧的最好办法就是面对恐惧,坚持,才是胜利!加油,奥利给!

没毛病,干就完了,奥利给!

 

 

 

 

 

然并卵,哈哈哈。

 

四、 如何通过LeetCode来进行算法题目练习

常见练习场景

场景1

拿到题目后就开始想着怎么写代码,结果写了大半天,试着做了半天,不对,再继续写,还是不对,f**k,这么难,大sb,不做了

场景2

看完题目,这是要干啥,完全不知道怎么下手。

 

一些微小的算法学习经验

其实,学算法,刷题蛮干是不行的,需要遵循科学的方法。

算法不是拼智商

算法不是纯粹拼智商的,智商高,就一定很厉害,不够聪明,就一定不行。算法是一种技能,是可以通过科学合理的方式训练出来的能力。

智商的高低,当然会有影响,但这个先天因素无法改变,而科学合理的方法是大家都可以掌握的。

所以,首要的一点,是要意识到,算法不是只拼智商的,也是可以经由后天训练习得的。

 

难度要循序渐进

有些同学喜欢上来就是干,上来就是终极难度的题目,觉得自己只要做出最难的,其它的就迎刃而解了。这种急于求成的思想要不得。

算法训练是一个系统工程,需要循序渐进,太过于急功近利,反而容易因做不出难题而产生挫败感,带来反效果。

 

选择题目不要看标签

不要看标签,不要看标签,不要看标签。标签相当于问题的分类,看了标签就会往那个方向去想,不利于自主思考。

 

练习时使用番茄时钟

番茄时钟是啥?百度一下

分配时间大概如下

 

第一阶段:

分析阶段:读完题目,分析大概的要点,可能需要的知识点,此阶段不动手,仅仅动脑。

在分析推导题目解法的时候,不要去想任何实现相关地事情,不用去想代码怎么写,不用去想要用什么库,定义什么变量,用多少层循环,都不要想,就想着在逻辑上,这道题目要怎么解。

这样做可以极大地降低你的心智负担,使你高效地想出题目的解法。对于如何将想法变成代码,可以留在下一个步骤,单独来进行。

 

用时:1个番茄钟,最多2个番茄钟

重要的一点:如果最多2个番茄钟过完,还是没有任何思路,直接看解法,各种别人的解法,这不是抄答案!

然后背诵并默写好的解法。直接应用五步刷题法。

第二阶段:

验证分析阶段:

代码写起来,注意一些常见的小错误有:

  • 拼写错误。变量命名要足够清楚,不要用单个字母或者语意不明的单词。

  • 数组边界未考虑。

  • 空值未考虑。

 

用时:1个番茄钟,最多2个番茄钟。

注意:

如果中间发现了分析阶段的错误或者疏漏。应该立即结束编码,休息。

并且重新开启分析阶段的时钟。

如果是重新开始分析再次进入代码验证分析阶段,还是做的不对,用时超过3个番茄钟,直接看讨论或者答案。

 

切忌边写边改方案。如果发现编码过程状态不够好,应该加长休息时间,或者干脆结束掉。不要给自己留下低效的映像。

去开开心心的玩游戏,看电影吧,哔哩哔哩刷起来,别练习了。

 

 

第三阶段:

进行解题分享阶段:

 

分享时,建议大家就把自己番茄时钟的执行记录进行分享。最后标准的解法以及思路其实在 discussion 中都有。对他人有用的分享不是结果,而是:

  • 你在番茄时钟中是如何规划的,也就是番茄时钟的目标。

  • 你是如何分析,也就是思路。

  • 你的结论是什么,或者是你在执行时除了什么问题。

  • 你所总结出的题目的关键部分。也就是对问题域进行探索的经验。

 

五步刷题法

刷题第一遍:

  • 5~10分钟:读题思考

  • 直接看解法,去国际站看最高票的回答

  • 背诵、默写好的解法

  • 多解法,比较解法优劣

刷题第二遍:

  • 马上自己打开浏览器写->leetcode提交

  • 多种解法比较、体会->优化

刷题第三遍:

  • 一天后,再重复刷题

  • 不同解法的熟练程度->专项练习 刷题第四遍:

  • 一周后:反复回来练习相同题 刷题第五遍:

  • 面试前一周恢复性训练

     

认真学习,坚持训练。

 

最大的误区

做算法题只做一遍!!!

 

 

关键的关键

  • 现在就动手

  • 注册LeetCode

  • 练习-坚持-机会给予有准备的人

 

参考资料

[1]https://blog.csdn.net/u013164931/article/details/80189351

[2]https://www.cnblogs.com/kubidemanong/p/11847944.html

[3]https://blog.csdn.net/weixin_41278720/article/details/90268965

原文地址:https://www.cnblogs.com/Nicholas0707/p/12716512.html