目录
数据结构 - 集合 set
特点
集合的特点:无序,元素不重复
主要作用
1.检查某元素是否存在
2.检查是否有重复元素(方法:比较原数据集和对应集合的长度)
分类
hashset(常见)、linklistset、treeset …
hashset 添加元素的过程:元素→哈希函数→哈希值→放到哈希表相应位置(1.无元素时,直接存;2.有元素且相等时,更新;3.有元素且不等时,产生哈希冲突)
解决哈希冲突的方法:链表法(和之前的笔记一样)
时间复杂度
访问:不能通过索引访问元素
搜索、插入、删除:
(1)无哈希冲突:O(1)
(2)有哈希冲突:O(K),K是冲突元素的个数
常用操作
# 创建集合
s = set()
# 添加元素
# O(1)
s.add(10)
# 搜索元素
# O(1)
2 in s
# 删除元素
# O(1)
s.remove(2)
# 长度
# O(1)
len(s)
数据结构 - 树 tree
特点
树在工作中一般自己单独使用的机会很少
树中的节点存在父子关系
TreeNode 可以作为队列的元素,但不能作为列表的元素
树的节点分类
节点:所有点
根节点:最顶端的点
叶子节点:没有子节点的节点
概念:高度、深度、层
二叉树
1.普通二叉树:每个节点最多2个孩子
2.满二叉树:除了叶子节点,每个节点都有左右2个孩子,且所有叶子节点都在同一层上
3.完全二叉树:从树的根节点,从上到下、从左到右依次填满节点形成的二叉树
若一个树是满二叉树,则一定是完全二叉树;若一个树是完全二叉树,它不一定是满二叉树
二叉树的遍历
数据结构 - 堆 heap
特点
堆属于完全二叉树,分为最大堆和最小堆
分类
最大堆:每个节点的值都 >= 它的孩子节点,该堆的最大值是堆顶元素
最小堆:每个节点的值都 <= 它的孩子节点,该堆的最小值是堆顶元素
时间复杂度
堆化(创建堆):O(N),包括2个步骤:(1)遍历原结构,生成完全二叉树,O(N);(2)交换节点位置,直至符合堆的特点,O(N)
访问:不存在,不能通过索引访问元素
搜索:O(1),一般指搜索堆顶元素
添加:O(logN),每添加一个元素,都需要与父节点比较大小,若不符合堆的特点则父子节点交换位置,一直不符合则一直比较至堆顶元素,直至符合堆的特点
删除:O(logN),一般指删除堆顶元素。删除后,将最末尾的元素移至堆顶,若不符合堆的特点,则该元素需要一直与对应子节点的最大/最小值交换位置,直至符合堆的特点
常用操作
import heapq
class Test:
def test(self):
# 创建最小堆
minheap = []
heapq.heapify(minheap)
# 若创建最大堆,需要先将所有元素乘-1,然后创建最小堆,最后将最小堆的元素乘-1
# 添加元素
heapq.heappush(minheap,10)
# 查看堆元素
print(minheap)
# 查看堆顶元素
print(minheap[0])
# 删除堆顶元素
heapq.heappop(minheap)
# 长度
len(minheap)
# 遍历
while len(minheap) != 0:
print(heapq.heappop(minheap))
数据结构 - 图 graph
概念
每个节点称为顶点,与顶点相连的节点是邻居节点,对应的边是度(degree)
分类
无向图,有向图,权重图
有向图的一些概念:
入度:多少边指向该顶点
出度:多少边以这个点为起点指向别的顶点
权重图:可用于计算最短路径
数据结构的常见面试题
1.比较多种数据结构:除了说定义,还需要比较各自的时间复杂度(访问、搜索、插入、删除)、适用场景(读 / 写)
2.哈希碰撞的解决方法
3.数据结构与实物的联想
队列 - 水管(先入先出)
栈 - 杯子(先入后出)
算法 - 双指针 two pointers
分类
普通双指针:两个指针往同一个方向移动(也有可能不是同方向)
# 找出和为12的2个不同元素
# O(N²)
a = [1,4,5,7,9] # 此处a是升序数组
for i in range(len(a)):
for j in range(i,len(a)):
if i+j == 12:
print(i,j)
对撞双指针:两个指针面对面移动
# O(N)
a = [1,4,5,7,9] # 此处a是升序数组
i = 0
j = len(a)
while True:
if i+j == 12:
print(i,j)
break
elif i+j < 12:
i += 1
elif i+j > 12:
j -= 1
快慢双指针:慢指针+快指针
检测链表是不是环形链表:设置2个指针,一快一满,同时从起点出发,若两者中途相遇,说明是环形链表