Skip to content

Latest commit

 

History

History
 
 

字典树和并查集 字典树(Trie) 数据结构: 单词查找树或键树,是一种树形结构。典型应用是用于统计和排序大量字符串(但不限于字符串),所以经常被搜索引擎系统用于文本词频统计 优点: 最大限度地减少无谓的字符串比较,查询效率比哈希表高 核心思想: 基本性质: 1、节点本身不存完整单词 2、从根节点到某一节点,路径上经过的字符串连接起来,为该节点对应的字符串 3、每个节点的所有子节点路径代表的字符串不相同

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

高级搜索
    剪枝
    双向BFS
    启发式搜索(A*)
初级搜索
    1、朴素搜索
    2、优化方式:不重复、剪枝(括号生成)
    3、搜索方向:
        BFS:广度优先搜索
        DFS:深度优先搜索

双向BFS模板实现

class Solution { function ladderLength($beginWord, $endWord, $wordList) {

    //1、设置set查找
    $hashList = array_flip($wordList);
    if (!isset($hashList[$endWord])) return 0;
    unset($hashList[$beginWord]);

    //2、初始值 模拟队列
    $beginVisited[$beginWord] = true;
    $endVisited[$endWord] = true;
    $visited = [];
    $step = 1; // 默认1步
    $wordLen = strlen($beginWord);

    //3、循环查找
    while (!empty($beginVisited) && !empty($endVisited)) {
        //4、大小交换,只循环小的元素
        if (count($beginVisited) > count($endVisited)) {
            list($beginVisited,$endVisited) = [$endVisited,$beginVisited]; // 数组交换
        }
        //5、循环逻辑处理
        $nextLevelVisited = [];
        foreach ($beginVisited as $word => $value) {
            for ($i=0; $i < $wordLen; $i++) {
                $old = $word[$i];
                for ($k=97; $k <= 122; $k++) { // 条件逻辑
                    if ($old == chr($k)) continue;
                    $word[$i] = chr($k);
                    if (isset($hashList[$word])) {
                        if (isset($endVisited[$word])) return $step+1; // 判断是否存在
                        if (empty($visited[$word])) {
                            $nextLevelVisited[$word]
                            = true;
                            $visited[$word] = true;
                        }
                    }
                }
                $word[$i] = $old; // 恢复值
            }
        }
        // 6、进行下一次循环
        $beginVisited = $nextLevelVisited;
        $step++;
    }
    return 0;
}

}

启发式搜索

    A* search
        https://shimo.im/docs/8CzMlrcvbWwFXA8r/read
        BFS 队列改成优先级队列,有一个估价函数
        估价函数:
            启发式函数:h(n),它用来评价那些结点最有希望的是一个我们要找的结点,h(n)会返回一个非负实数,也可以认为是从结点n的目标结点路径的估计成本
            启发式函数是一种告知搜索方向的方法。它提供了一种明智的方法来猜测那个邻居结点会导向一个目标
            算法:https://zxi.mytechroad.com/blog/searching/8-puzzles-bidirectional-astar-vs-bidirectional-bfs/
AVL树(二叉搜索树)
    1、平衡因子 -1,0,1
        由来:因为查询时间复杂度等于树的深度,所以需要记录树的深度差
    2、旋转操作来保持平衡
        左旋、右旋、左右旋[左右子树]、右左旋[右左子树]
    不足:结点需要存储额外信息,且调整次数频繁[维护成本高]。所以会引入近似平衡二叉树
红黑树 (近似平衡二叉搜索树)
    它能够确保任何一个结点的左右子树的高度差小于两倍。具体来说,红黑树是满足如下条件的儿茶搜索树:
        1、每个结点要是红色,妖魔是黑色
        2、根节点是黑色
        3、每个叶结点(NIL结点,空结点)是黑色
        4、不能有想邻接的两个红色结点
        5、从任一结点到其每个叶子的所有路径都包含相同数目的黑色结点
对比
    AVL 优秀的地方时,查询相对更好
    红黑树 添加删除 相对来说更好
    红黑树 存储信息更小,消耗更少的空间
    读操作多用AVL树,如果插入操作也比较多那么用红黑树

跳跃表与红黑树比较
    1、算法实现难度相对来说简单
    2、范围查询更快捷
        平衡树需要以中序遍历的顺序继续寻找其它不超过大值的节点。
        skiplist进行范围查找非常简单,只需要在找到小值之后,对第1层链表进行若干步的遍历就可以实现
    3、插入和删除相对来说更简单
        平衡树的插入和删除操作可能引发子树的调整,逻辑复杂,而skiplist的插入和删除只需要修改相邻节点的指针,操作简单又快速