实现语言Python,C++ #学习资料
(一)常见七种复杂度
- O(1) : Constant Complexity
- O(n) :Linear Complexity
- O(n2) : N square Complexity
- O(n3) : N cubic Complexity
- O(2n) : Exponential Complexity
- O(logn) : Logarithmic Complexity
- O(n!) :Factorial
(二)支配定理
对于递归方法的复杂度分析,可使用master theorem定理来分析
参考:wiki百科-支配定理
(三)数据结构的操作复杂度
- 普通链表:lookup的复杂度为O(n),append、insert、delet为O(1)
- 列表:insert、delete的复杂度为O(n),append、lookup为O(1)
- 跳表:取代平衡树二分查找,多级索引进行加速查找,lookup复杂度降低为O(logn;但是维护成本高,空间换时间
(四)刻意训练方法
- 5~10分钟思考,有思路可以实现,没有思路直接看题解
- 看题解,背诵熟练(有的解法不好 可以不看)
- 闭卷测试
- 练习结果主要看时间,空间暂不考虑
- 同一题要多练几遍!!!,看看网友的优秀方法
(1)二叉树遍历方式
树的循环比较麻烦,常用递归的方式
1.前序pre-order : 根-左-右
2.中序in-order : 左-根-右
3.后序post-order : 左-右-根
(2)二叉搜索树
- 特征:左子树上所有节点均大于根节点的值;右子树上所有节点的值均大于根节点的树。
- 搜索树的搜索时间复杂度为:O(logn)
- 二叉搜索树demo .
##2.0工具包utils.py
- 函数计时器:function_timer(func)
使用Python修饰器实现
在定义的函数前面一行 插入一行 @function_timer
即可查看此函数运行时间
- 随机数组生成器:generateRandomArray(length,rangeL,rangeR)
返回length长度,且在(rangeL,rangeR)范围内的整数数组
- 检验排序是否正确:isSort(array)
##2.1 & 2.2选择排序
基本思路:遍历列表中的值,搜寻该值以后所有值中的最小值,与之替换。
时间复杂度:O(n2)
Python实现结构体:使用Class做定义,手动初始化和排序
##2.3插入排序
基本思路:遍历列表中的值,选中以后插入有序列表中的应有的位置,理论上通常比选择排序快一点,对于近乎有序的列表,速度提升会更明显,某些情况下速度会比一些O(n logn)算法更快。
时间复杂度:O(n2)
算法改进:实际操作时,发现插入排序反而比选择排序耗时。因为虽然判断的少,但是交换次数多,耗时反而比较长。
因此优化方法为:先把遍历位置的值取出保存,再与前一个比较大小,如果前一个大于当前值,则直接将前一个值后移。
如果小于则将缓存放在此处,减少交换产生的赋值次数。
值得注意的是,使用python内置的函数实现排序要比手动逐个实现要快得多。
算法:选择排序
程序运行:1.140265 s
算法:插入排序
程序运行:2.170480 s
算法:插入排序-改进1次后
程序运行:1.520350 s
算法:插入排序-改进3次后
程序运行:0.641137 s
##2.4希尔排序 基本思路:插入排序对于小规模或者基本有序的数组排序效率高,但是对于大规模无序数组则无优势。希尔排序通过把大规模无序数组分割成若干个小规模数组进行排列,实现对大规模无序数组同样拥有优势。
算法:优化后插入排序
程序运行:0.561127 s
算法:希尔排序
程序运行:0.021004 s
#第三章:高级排序
上一章的排序方法为常见基础排序,复杂度为O(n2)级别,
这一章介绍的排序方法复杂度级别为O(nlogn)
##3.1归并排序
基本思路:假设已经右两个已经排好序的子数组,并且和原来数组不在同一个存储空间。两个数组各有一个指针做追踪,还有一个最终生成位置的首部指针,依次移动,判断从哪个子数组中取出值存放进去。
##3.2快速排序
被誉为20实际最伟大的算法之一
基本思路:选中一个元素,想办法在数组中左边均小于他,右边均大于他(partition)。
问题:实际上如果排列近乎有序的列表,当规模大的时候,速度远远低于归并排序。
##3.2双路快速排序
程序运行:1.816214 s -快速排序
程序运行:1.807245 s -随机快速排序
程序运行:0.045031 s -双路快排
基本思路:随机选取一个值放在最左边,左边从l+1开始,右边从r开始遍历,保证i左边j右边分别为小于v和大于v的值。
直到i,j均指到不满足条件的值,这时候再调换i,j中的值继续运行。
优点:对于键值少,重复多的排序更快。
##3.3三路快速排序
基本思路:三路快排是在双路的基础上,多分了个等于v的部分。因此,原来的p分为两部分,变成了lt、gt分为三部分。
区别:三路快排对于重复值多的排序比双路快排快,但是对于重复少的反而不如双路快排。
#第四章:堆
先验知识:
- 普通队列:先进先出,后进后出
- 优先队列:出队顺序和入队顺序无关,和优先级有关
- 优先队列的特色,例如在N个元素中寻找前M个元素,如果用高级排序大概是NlogN复杂度,但是通过优先队列,可以降维NlogM复杂度。
入队 | 出队 | |
---|---|---|
普通数组 | O(1) | O(n) |
顺序数组 | O(n) | O(1) |
堆 | O(lgn) | O(lgn) |
- 二叉堆:Binary Heap,子节点不大于父节点。而且是完全二叉树,即有限满足最左面的子节点。
- 二叉堆的性质:
①i节点的parent节点为i/2
②i节点的左子节点为2i
③i节点的右子节点为2i+1