一、数据结构和算法总览
1.刻意练习
过遍数:五毒神掌 ; 刻意练习自己的弱项
练习基本功很重要
主动式反馈 : 寻求更好的方法和方式:leetcode高手代码
被动式反馈 : code review 教练指点
需要得到肌肉式记忆
2.环境配置及工具类
command + left/right : 去到行头行尾
Option + left/right : 光标按单词切分
Shift + command + right : 当光标在行头的时候,选中整个行
Ctrl+N:到下一行
Ctrl+P:到上一行
Ctrl+1K:从光标处开始删除,直到行尾
Fn + delete : 向后删除
自顶向下的编程方式,借鉴新闻稿的形式
最关键的东西最有价值的东西放前面,不要写成散文,看了半天看不懂在干嘛。最关键的函数放前面
二、时间复杂度、空间复杂度
1.常用时间复杂度表和对比图
假设N等于多少的时候,程序会执行x次,那么这个n和x的关系,就是时间复杂度了
需要对自己写的程序的时间和空间复杂度了解,写完之后要分析时间和空间复杂度。越简单程序执行越快越高效
1.1 小结
一维的数组进行二分查找,就是logn
二维的矩阵查找,有序的矩阵进行查找,这时候被降了一维就不是n平方的算法,是O(n)
归并排序 O(nlogn),是最好的!!
1.2 面试常考
-
二叉树遍历-前序、中序、后序写一下程序,然后时间复杂度是多少
时间复杂度是O(n),n就是二叉树里面的节点总数。
为什么?不管是前序中序后序它遍历二叉树的时候每个节点会访问一次且仅访问一次。所以它的时间复杂度就是线性于二叉树的节点总数,也就是O(n)的复杂度
-
图的遍历,时间复杂度是多少?
- 图里面的每个节点访问一次且仅访问一次,所以它的时间复杂度是O(n),这里的n就是图里面的节点总数
-
搜索算法:DFS(深度优先) 、BFS(广度优先) 时间复杂度是多少?
- 节点都只访问一次,所以是O(n),n指的是搜索空间里面的节点总数
-
二分查找时间复杂度是多少?
- logn
2.空间复杂度
如果代码里面开了数组,那么数组的长度基本上就是你的空间复杂度
比如开了一维数组,那么就是O(1)
如果开了二维数组,是数组的n平方,那么空间复杂度就是n平方的。O(2^n)
如果有递归的话,递归最深的深度就是空间复杂度的最大值
如果又有递归又有数组的话,那就是两者之间的最大值就是空间复杂度
三、数组、链表、跳表
1.三者的数据结构和基本特性
1.1数组Array
用Python的语法就是 list = []
增加删除引起群移,时间复杂度是O(n)
查找是O(1)
1.2链表Linked list
头指针: head ; 尾指针: tail ; 节点 : node
单链表:只有一个next指针
双向链表:有next指针和prev指针
循环链表: tail的next指向head
增加删除 : 时间复杂度 O(1)
头结点和尾节点查找是O(1),其他节点查找是O(n)
1.3跳表 skip list
升维思想,空间换时间
跳表只用于链表里元素有序的情况,也就是跳表里面的里面的元素始终必须是有序的
所以跳表对标的是二叉搜索树种的平衡树(AVL Tree)和二分查找
插入、搜索、删除时间复杂度都是O(logn)
四、栈、队列、优先队列、双端队列
-
栈stack:先入后出(first in last out)
- 添加删除O(1),因为是无序的所以查询O(n)
-
队列queue : 先入先出(first in first out )
- 添加删除O(1),因为是无序的所以查询O(n)
-
双端队列deque(double-end queue): 头和尾都可以进行元素的出和入
- 添加删除O(1),因为是无序的所以查询O(n)
-
优先队列priority queue:
插入O(1)
取出O(logn) 即按照元素的优先级取出
底层具体实现的数据结构较为多样和复杂: heap、bst(binary search tree 二叉搜索数)、treap
五、哈希表、映射、集合
1.哈希表
Hash function
通过哈希函数把要存储的值映射到一个位置,位置就是它的下标index
Hash collisions
通过哈希函数得到的下标值一样就是哈希碰撞
可以用拉链式解决冲突法,在碰撞的地方增加维度,拉一个链表
哈希表可以认为都是O(1)的复杂度,计算机内存大,哈希表可以开很大
2.映射和集合
从哈希表抽象出来的常用map和set (map就是Python的dict)
map(键值对 key-value): key不可以重复,value可以重复
set (单个元素): 不重复元素的集合