why?
为什么要写这一系列文章?为什么要学数据结构与算法?
我的内心独白是,我菜呀,不学不看不记,怎么进步?所以必须得刻意学习,刻意记录,刻意分享。才能掌握熟练,我相信对于一部分人是很适用的。
不用我说,为什么学?大家心里都有自己的考量。如果你日常工作中用得少,也正常。那是因为业务场景还没达到,而不是说它工作中没用。我自己是感觉到有几点很适用:
- 防范于未然,你先掌握熟悉算法,在未来的工作中,只要你是向前走的,总能有业务场景需要运用或理解的。
- 刻意学习,的确能锻炼出比较好的逻辑思维能力,解决问题能力。
- 表现自己,学好数据结构和算法不算一件容易的事,你越是能掌握它,也越能凸显你的学习能力。最重要也是能在面试过程中脱引而出。
当然,我任务学习数据结构和算法是要下很大决心的。它是一个长的过程,一蹴而就的想法真不适合学习它。所以我也想在这里立个flag。坚持学习记录并分享,不断试错前进,也总结出自己思考的观点,能让一起学习的同学少踩坑,对关键点印象能更深刻,有更平滑对学习曲线。之前自己学习也走了很多弯路,不明确,也浪费了很多时间。
推荐的学习路线
这系列的内容也是跟随着极客时间的课程,边学习边记录。之后章节内容会对每一个板块标记重点,并通过leetcode相应题目解析加强数据结构和算法的印象,边学边写。
👌开始
对数据结构和算法的认识
对它有个内心的总体印象,之后遇到问题就会有更好的领悟。数据结构大致可以理解为**存储一组数据的结构,算法就是操作这组数据的方法。**经过前人大牛们的总结,已经有了很多著名的数据结构用来存储数据,如:队列、栈、二叉树等,也有很多经典的算法:二分法、动态规划等。数据结构和算法是相辅相成的,算法作用在特定的数据结构上更能发挥作用,数据结构也不能独立于算法存在,是不具有应用意义也不高效的。
重点知识
一个领域的内容,如果不能全力探索,你也可以抓住重点方向学习,也足已应对大多数场景。
- 复杂度分析
- 数据结构:数组、链表、栈、队列、散列表、二叉树、堆、跳表、图、Trie 树
- 算法:递归、排序、二分查找、搜索、哈希算法、贪心算法、分治算法、回溯算法、动态规划、字符串匹配算法。
配合相关leetcode题练习、并解析。总结特点,套路,从而应对各式问题和场景。如果在写题的过程中,困扰很久。千万别专牛角尖,可以直接看解析分享,再总和自己的理解。再写一遍,效率会更高。
复杂度分析
时间复杂度
**用于大致的分析一段代码的执行效率、与环境无关。我们假设不同环境中每行代码的执行时间是一样的。时间复杂度的另一个考量就是数据规模n。O(f(n))表示的这个方法在数据规模为n的情况下的大致执行效率。时间复杂度总体表示的是代码执行时间随数据变化的增长趋势。
3个技巧去简单分析一段代码的时间复杂度
- 只关注循环执行次数最多的代码、和数据规模相关的部分
function o (n) {
const a = 1
const b = 2
let sum = a + b
for (let i = 0; i < n; i++) {
sum += i
}
// for (let i = 0; i < n; i++) {
// sum += i
// }
return sum
}
这段代码中会先执行前3行,进入循环执行内容n次(每次循环假设1次),返回时再执行1次。客观来说,总执行数是n+4。我们只需关系执行时与数据n有关的,其他都是**常量级别的不需关心,哪怕是有两段相同的循环。**这个函数的时间复杂度都为O(n)。
- 总复杂度等于量级最大的代码段的复杂度
function o (n) {
const a = 1
const b = 2
let sum = a + b
for (let i = 0; i < n; i++) {
sum += i
}
for (let i = 0; i < n; i++) {
for (let j = 0; j < n; j++) {
sum += j + i
}
}
return sum
}
这段代码后半段,循环中嵌套了循环,其中的最里层的循环代码执行了n*n次,已经成为这个函数量级最大的次数。
所以这个函数的时间复杂度为O(n^2)。
- 嵌套代码的复杂度等于内外的乘积
参考上例代码分析完复杂度为O(n^2)。
常见的时间复杂度有:
空间复杂度
表示的是存储空间与数据规模之间的增长关系。
function area (list) {
const other = 0
const arr = new Array(list.length)
for (let i = 0; i < list.length; i++) {
arr[i] = list[i] + i
}
return arr
}
从上例代码中,我们看到定义了一个other变量,申请一个空间且与list无关。以及一个arr数组,数组的所需空间等于list的空间。浅显移动,在这段代码中我们额外需要的空间为1+n(n表示数组list的空间),所以空间复杂度也为O(n)。空间复杂度的分析并不常见,我们先掌握基本概念。
下一步
当然这几点都是很基础的分析,复杂度的概念还不止如此,需要多看不同的文章去加深理解。本系列的重点内容是后续的算法题案例。所以这里就不多做分析(主要是我还菜,理解不够透彻)。
下一章开始,针对每一种常见的数据结构和算法,结合题目进行讲解。希望能坚持✊下去。