极客时间 算法训练营 第六周总结

学习总结

学习内容

字典树 Trie

  1. 字典树的数据结构

  2. 字典树的核心思想

  3. 字典树的基本性质

基本结构

字典树,即 Trie 树,又称单词查找树或键树,是一种树形结构。典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。

优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高。

基本性质

  1. 节点本身不存完整的单词
  2. 从根节点到某一结点,路径上的字符连接起来就是该结点对应的字符串
  3. 每个结点的所有子结点路径代表的字符都不相同

极客时间 算法训练营 第六周总结_第1张图片

核心思想

核心思想是空间换时间

利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的

字典树代码模板

class Trie:

    def __init__(self):
        self.root = {}  # 根节点
        self.endofword = "#"    # 标识是否是一个完整的单词
        

    def insert(self, word: str) -> None:
        # 插入操作
        node = self.root    # 根节点
        for char in word:   # 遍历单词 word 中每个字符
            node = node.setdefault(char,{}) # 字典形式依次将字符保存到树的每一层中
            # dict.setdefault(key, default=None) 如果 key 在 字典中,返回对应的值。
            # 如果不在字典中,则插入 key 及设置的默认值 default,并返回 default ,default 默认值为 None。
        node[self.endofword] = self.endofword   # 完整单词标识
        

    def search(self, word: str) -> bool:
        # 查找操作
        node = self.root
        for char in word:   # 遍历单词 word 中每个字符
            if char not in node:    # 未找到
                return False
            node = node.get(char)   # 找到进入下一结点
        return self.endofword in node # 是否为完整的单词
        

    def startsWith(self, prefix: str) -> bool:
        # 字典树中是否有以 prefix 为前缀的单词
        node = self.root
        for char in prefix: # 遍历 前缀 prefix
            if char not in node:
                return False
            node = node.get(char) 
        return True


# Your Trie object will be instantiated and called as such:
# obj = Trie()
# obj.insert(word)
# param_2 = obj.search(word)
# param_3 = obj.startsWith(prefix)

并查集 Disjoint Set

应用:组团、配对问题

基本操作

  • makeSet(s):建立一个新的并查集,其中包含 s 个单元素集合。
  • unionSet(x, y):把元素 x 和元素 y 所在的集合合并,要求 x 和 y 所在的集合不相交,如果相交则不合并。
  • find(x):找到元素 x 所在的集合的代表,该操作也可以用于判断两个元素是否位于同一个集合,只要将它们各自的代表比较一下就可以了。

初始化

极客时间 算法训练营 第六周总结_第2张图片
每个元素的parent指向自己

查询、合并

极客时间 算法训练营 第六周总结_第3张图片

路径压缩

极客时间 算法训练营 第六周总结_第4张图片

并查集代码模板


class UnionFind:

    def init(self,p,n):
        # 初始化 元素指向自己  parent 结点是自己
        p = [i for i in range(n)] 
    
    def union(self, p, i, j): 
        p1 = self.parent(p, i)  # 找 i j 各自的领头元素 
        p2 = self.parent(p, j) 
        p[p1] = p2

    def parent(self, p, i):  # 找 i 的 领头元素
        root = i
        while p[root] != root: # parent 结点不是自己
            root = p[root] # 不断向上 直到直到领头元素
        
        # 路径压缩 将i到root沿途所有结点指向root
        while p[i] != i:
            # x = i; i = p[i]; p[x] = root
            i,p[i] = p[i],root

        return root

高级搜索

相对于朴素搜索,
优化方式:
不重复(fibonacci)、剪枝(生成括号问题)、
搜索方向:
DFS: depth first search 深度优先搜索
BFS: breadth first search 广度优先搜索

剪枝
把没有必要的分支减掉(重复、次优解)

双向bfs
分别从起点和终点分别bfs搜索,直到相遇

启发式搜索
实现优先级的搜索
估价函数
启发式函数: h(n),它用来评价哪些结点最有希望的是一个我们要找的结
点,h(n) 会返回一个非负实数,也可以认为是从结点n的目标结点路径的估计成本。
启发式函数是一种告知搜索方向的方法。它提供了一种明智的方法来猜测哪个邻居结点会导向一个目标。

平衡树

二叉搜索树在极端情况退化为链表
为了保证性能,就要左右子树结点平衡

AVL 树

Balance Factor(平衡因子)

是它的左子树的高度减去它的右子树的高度(有时相反)。
balance factor = {-1, 0, 1}

通过旋转操作来进行平衡(四种)

根据不平衡时结点情况

  1. LL情况:左旋

  2. RR情况:右旋

  3. LR情况:左右旋

  4. RL情况:右左旋

红黑树

红黑树是一种近似平衡的二叉搜索树(Binary Search Tree),它能够确保任何一个结点的左右子树的高度差小于两倍。具体来说,红黑树是满足如下条件的二叉搜索树:

• 每个结点要么是红色,要么是黑色

• 根节点是黑色

• 每个叶节点(NIL节点,空节点)是黑色的。

• 不能有相邻接的两个红色节点

• 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。

你可能感兴趣的:(算法训练营总结)