一、入门
1.数据结构与算法
1.从广义上来讲,数据结构就是一组数据的存储结构,算法就是操作数据的一种方法。
数据结构是为算法服务的,算法服务于特定的数据结构之上。
2.为什么要学习数据结构与算法呢?
计算机的计算能力是有限的,这么大量的数据计算,需要越来越多的计算机,需要越来越长的计算时间,注重效率的我们需要尽可能的提高计算效率。其中重要的一项,就是使用合适的数据结构和算法。选用合适的数据结构和算法,特别是在处理体量非常庞大的数据的时候,可以极大提高计算效率。
3.基础常用的数据结构与算法(掌握):
10个数据结构: 数组,链表,栈,队列,散列表,二叉树,堆,跳表,图,Trie树
10个算法: 递归,排序,二分查找,搜索,哈希算法,贪心算法,分治算法,回溯算法,动态规划,字符串匹配算法
4.复杂度:
数据结构本身解决的是“快”和“省”的问题,能够让代码运行的更快,并节省存储空间。
复杂度分析是整个算法学习的精髓,只要掌握了它,数据结构和算法的内容基本上就掌握了一半。
为什么需要复杂度分析呢?
1.测试结果非常依赖测试环境。
2.测试结果受数据规模的影响很大。
分析下面代码:
那么可以得出一个重要的结论:所有代码的执行时间T(n)与每行代码的执行次数n成正比。
时间复杂度:大O时间复杂度实际上并不具体代表代码的执行时间,而是表示代码执行时间随数据规模增长的变化趋势。所以也叫渐进时间复杂度。
分析要点:
1.只关注循环执行次数最多的一段代码
2.加法法则:总复杂度等于量级最大的那段代码的的复杂度
3.乘法法则:嵌套代码的复杂度等于嵌套内外代码复杂度的乘积
a. O(1)
一般情况下,只要算法中不存在循环语句、递归语句,即使有成千上万行的代码,其时间复杂度也是Ο(1)。
b. O(logn)、O(nlogn)
在采用大 O 标记复杂度的时候,可以忽略系数,即 O(Cf(n)) = O(f(n))。所以,O(log2n) 就等于 O(log3n)。因此,在对数阶时间复杂度的表示方法里,我们忽略对数的“底”,统一表示为 O(logn)。
c.O(m+n)、O(m*n)
m 和 n 是表示两个数据规模。我们无法事先评估 m 和 n 谁的量级大,所以我们在表示复杂度的时候,就不能简单地利用加法法则,省略掉其中一个。所以,上面代码的时间复杂度就是 O(m+n)。
空间复杂度:全称就是渐进空间复杂度(asymptotic space complexity),表示算法的存储空间与数据规模之间的增长关系。
思考1:为什么要进行复杂度分析?
1.和性能测试相比,复杂度分析有不依赖执行环境、成本低、效率高、易操作、指导性强的特点。
2.掌握复杂度分析,将能编写出性能更优的代码,有利于降低系统开发和维护成本。
思考2:常用的复杂度级别?
多项式阶:随着数据规模的增长,算法的执行时间和空间占用,按照多项式的比例增长。包括,
O(1)(常数阶)、O(logn)(对数阶)、O(n)(线性阶)、O(nlogn)(线性对数阶)、O(n^2)(平方阶)、O(n^3)(立方阶)
非多项式阶:随着数据规模的增长,算法的执行时间和空间占用暴增,这类算法性能极差。包括,
O(2^n)(指数阶)、O(n!)(阶乘阶)
浅析最好、最坏、平均、均摊时间复杂度
1.最好情况时间复杂度就是,在最理想的情况下,执行这段代码的时间复杂度。
2.最坏情况时间复杂度就是,在最糟糕的情况下,执行这段代码的时间复杂度。
要查找变量x在数据中的位置,有n+1种情况,在数组的0~n-1位置中和不在数组中,需要把每种情况统计累加并除以n+1,这种值叫做加权平均值,也叫做期望值,所以平均时间复杂度的全称应该叫加权平均时间复杂度或者期望时间复杂度。
均摊时间复杂度就是一种特殊的平均时间复杂度,对一个数据结构进行一组连续操作中,大部分情况下时间复杂度都很低,只有个别情况下时间复杂度比较高,看是否能将较高时间复杂度那次操作的耗时,平摊到其他那些时间复杂度比较低的操作上。