一,字典树
字典树的基本性质
上图展示了字典树中的节点可以存储这个词出现的频次,这样在搜索时就可以根据频次来推荐,当然不限于只存储频次,也可以存储其他信息。
节点的内部实现
不是使用left和right来实现,而是直接使用字符指向下一个字符,如果只是简单的字母还不区分大小写就是26个分叉,如果是整个字符串的话ASCII码就是255,一共有255个分叉,一般是26个分查的多叉树,如果是叶子节点的话就指向空。
我们在构造字典树的时候可以是动态的,出现一个单词就构造一个分支,最大就是26个分支,所以是非常耗费空间的,一层就是26个分支,
单词的长度就是树的深度,所以查询是非常快的,查询次数等于单词长度,一般就是十几次,这样查询时间比排序+二分查找快很多,所以就得出了字典树的核心思想:
第二条的核心思想有个用处,就是我们只输入了前缀的前几个字母的话,可以把所有的以这个为前缀的候选词都方便的找出来。
二,并查集
并查集不像动态规划那些有很多的可以发挥的空间,并查集是有固定的使用场景和代码模板,在使用的时候直接调用现成的代码就好,这类题目比较固定,
适用场景:
并查集的基本操作:
1.创建一个并查集,使用数组或者set
并查集初始化:
并查集每个元素都有一个parent数组指向自己,说明自己是自己的集合。
合并查询:
查询:
从一个元素去找他的parent,,然后再找parent的parent,一直往上,直到元素的parent等于他自己的时候说明找到了领头羊。
合并:
将一个集合的领头元素指向另一个集合的领头元素。
路径压缩:
将一条路径上的元素的parent都指向a,这样和原来的表还是一样的,好处是查询的时间会快很多
并查集的Python实现:
首先创建并查集并遍历二维数组,当M[i][j]=1时合并ij,
最后看这个并查集李到底有多少个孤立的集合
路径压缩的作用是将所有的元素的parent指向根节点,这样的好处是下次再查找元素的parent时,时间时O(1)的。
怎么判断是否可以使用并查集:
类似于朋友圈,任意给两个人判断他们是不是朋友之类的问题。
一个比较好的并查集介绍
上面连接提供的代码模板:
class UnionFind:
def __init__(self):
"""
记录每个节点的父节点
"""
self.father = {
}
def find(self,x):
"""
查找根节点
路径压缩
"""
root = x
while self.father[root] != None:
root = self.father[root]
# 路径压缩
while x != root:
original_father = self.father[x]
self.father[x] = root
x = original_father
return root
def merge(self,x,y,val):
"""
合并两个节点
"""
root_x,root_y = self.find(x),self.find(y)
if root_x != root_y:
self.father[root_x] = root_y
def is_connected(self,x,y):
"""
判断两节点是否相连
"""
return self.find(x) == self.find(y)
def add(self,x):
"""
添加新节点
"""
if x not in self.father:
self.father[x] = None
作者:MiloMusiala
链接:https://leetcode-cn.com/problems/number-of-provinces/solution/python-duo-tu-xiang-jie-bing-cha-ji-by-m-vjdr/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
三,高级搜索
高级搜索的基础是对DFS,BFS这种初级搜索要熟悉
复习初级搜索:
初级搜索的内涵就是暴力搜索,初级搜索的优化方向是剪枝和和搜索方向。
像DFS这种就是傻瓜式搜索,不撞南墙不回头,没有任何的智能性,接下来这一部分会讲到优化的高级搜索:双向搜索和启发式搜索。
双向搜索:从起点和终点分别做一个广度优先,然后在中间相遇,这样时间更快。
启发式搜索:使用优先队列的数据结构,是按照节点的优先级,优先级高的先拿出来搜索,启发式搜索又叫A算法或者优先级搜索。
从零钱置换理解搜索问题:
搜索问题就是在状态树里使用DFS,或者BFS,优先级优先等方法得到最终我们想要的最优解,或者统计分支的个数。
3.1 剪枝
在状态树进行搜索的时候,如果我们发现某个分支是处理过的,我们就可以将其放在缓存中,整个分支就可以剪掉,不需要手动进行计算,有时候的话这个分支不够好,就是较差或者次优的分支,我们也可以将其剪掉.
3.2 双向BFS
从两端向中间扩散,当两端相遇时,结束,两边的步数相加就是最后的步数。
3.3 启发式搜索
是一种一遍搜索,一遍有思考的搜索方式,可以理解为思考式搜索,本质是通过优先级不断地去找优先级高的。
启发式搜索是基于BFS的:
代码模板如下:
启发式搜索的核心就是找到估价函数。
A*算法和BFS的对比
红黑树,AVL
复习:
树
二叉树
树的前中后序遍历
二叉搜索树
在极端情况下会出现棍子的情况,如下:
这个时候我们就需要用到了平衡二叉树,常用的平衡二叉树是AVL和红黑树。以及treap,splay(伸展树),B+树,二三树(应用在数据库的索引结构)
平衡二叉树的wiki
如何平衡二叉树:
AVL树
旋转操作:
动画
总结:
红黑树
是一种近似的平衡二叉树