前缀树学习

前缀树学习

1.长什么样子

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.重要的组成部分

class Trie {
    private Trie[] children;
    private boolean isEnd;

    public Trie() {
        children = new Trie[26];
        isEnd = false;
    }
}

假如我们只构建一个只有26个英文小写字母的前缀树

那么children的长度就是26 ,如果children[i] 不为空,那么证明有某个单词使用了这个前缀

3.插入方法

    public void insert(String word) {
        Trie node = this;
        for(int i = 0;i<word.length();i++){
            char ch = word.charAt(i);
            int index = ch-'a';
            if(node.children[index]==null){
                node.children[index] = new Trie();
            }
            node = node.children[index];
        }
        node.isEnd = true;
    }

1.从root节点开始->计算单词索引->插入到children的正确位置上->改变指针

遍历完成后,记得加上一个标识证明这里是一个结尾

4.搜索方法

private Trie searchPrefix(String prefix){
        Trie node = this;
        for(int i = 0;i<prefix.length();i++){
            char ch = prefix.charAt(i);
            int index = ch-'a';
            if(node.children[index]==null){
                return null;
            }
            node = node.children[index];
        }
        return node;
    }

搜索前缀的方法,差不多是插入方法的逆向思路

如果我们要找到某个单词,只用判断isEnd,或者判断是否存在某个前缀,只有判断是否为null

   public boolean search(String word) {
        Trie node = searchPrefix(word);
        return node!=null && node.isEnd;
    }
    
    public boolean startsWith(String prefix) {
        return searchPrefix(prefix)!=null;
    }

5.leetcode题目练习

208. 实现 Trie (前缀树) | 力扣 | LeetCode | 🟠

上文的前缀树的实现就是这题

648. 单词替换 | 力扣 | LeetCode | 🟠

可以先把字典构建一个前缀树

我们需要对搜索方法进行一个小小的修改

对于每个单词,需要进行替换,那么可以先创建一个StringBuilder

对该单词的每个字符,进行前缀树匹配,匹配上了,sb就append,然后移动前缀树指针,如果有某个字符匹配不上,直接返回单词原型

如果前缀树已经到了末尾,返回sb即可

211. 添加与搜索单词 - 数据结构设计 | 力扣 | LeetCode | 🟠

其实这里需要注意的就是通配符的处理

对于没有通配符,和上面正常搜索就行

有通配符,需要遍历每一个children 相当于就是dfs

677. 键值映射 | 力扣 | LeetCode | 🟠

这题,需要加一个字段也就是int val;代表值

首先根据searchPrefix方法找到前缀

然后计算和,计算代码如下

 public int prefixSum(Trie prefix){
        int sum = prefix.isEnd ? prefix.val : 0;
        for(int i = 0;i<26;i++){
            Trie child = prefix.children[i];
            if(child!=null){
                sum +=prefixSum(child);
            }
        }
        return sum;
    }
        if(child!=null){
            sum +=prefixSum(child);
        }
    }
    return sum;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值