【leetcode】替换单词

一、题目描述

在英语中,有一个叫做 词根(root) 的概念,它可以跟着其他一些词组成另一个较长的单词——我们称这个词为 继承词(successor)。例如,词根an,跟随着单词 other(其他),可以形成新的单词 another(另一个)。

现在,给定一个由许多词根组成的词典和一个句子,需要将句子中的所有继承词用词根替换掉。如果继承词有许多可以形成它的词根,则用最短的词根替换它。

需要输出替换之后的句子。

输入:dictionary = [“cat”,“bat”,“rat”], sentence = “the cattle was rattled by the battery”
输出:“the cat was rat by the bat”

二、 代码思路

很显然本题属于前缀树的应用

我们可以将词根存入前缀树,并在结束位置加上 end = true

我们可以对sentence(继承词)逐个遍历,观察改词是否在前缀树中有前缀。

如果有的话就替换,没有的话就原样输出。

这样的代码思路实际上有两种实现方法:

1、传统的维护一棵前缀树,使用 children[26] 孩子数组,来存储各个节点。

2、我们使用Hash来维护前缀树。

3、直接使用Hash表

首先将dictionary 中所有词根放入哈希集合中,然后对于 sentence 中的每个单词,由短至长遍历它所有的前缀,如果这个前缀出现在哈希集合中,则我们找到了当前单词的最短词根,将这个词根替换原来的单词。最后返回重新拼接的句子。

作者:LeetCode-Solution

三、 代码题解
class Solution {
    public String replaceWords(List<String> dictionary, String sentence) {
        //很显然本题属于前缀树的应用
        //我们可以将词根存入前缀树,并在结束位置加上 end = true
        //我们可以对sentence(继承词)逐个遍历,观察改词是否在前缀树中有前缀。
        //如果有的话就替换,没有的话就原样输出。
        Trie trie = new Trie();
        //加入前缀树中
        for (String word : dictionary) {
            trie.insert(word);
        }
        //判断sentence是否在前缀树中
        String words[] = sentence.split(" ");
        String res = "";
        for (int i = 0; i < words.length; i++) {
            String word = trie.getPrefixFromWord(words[i]);
            if (i == words.length - 1) {
                 res += word;
            } else {
                res += word + " ";
            }
        }
        return res;
    }
}
class Trie {
    //创建一个子节点数组,大小为26个,分别对应26个英文字母
    //但是该node节点对象并没有表示当前该节点存放的英文字母是什么
    //而是,利用数组26个大小区域是否为空 来判断对应的字符是否存在。
    private Trie[] children;
    private boolean isEnd;
    /** Initialize your data structure here. */
    public Trie() {
        children = new Trie[26];
        isEnd = false;
    }
    
    /** Inserts a word into the trie. */
    public void insert(String word) {
        //将当前对象作为一个节点
        //每个对象节点都有26个子节点
        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;
    }
    
    /** Returns if the word is in the trie. */
    public boolean search(String word) {
        Trie node = searchPrefix(word);
        //如果最后字符存在的node节点不为空,而且这个节点正好也是结束点,那么之前遍历的路径
        //连在一起就是一个目标字符
        return node != null && node.isEnd;
    }
    
    /** Returns if there is any word in the trie that starts with the given prefix. */
    public boolean startsWith(String prefix) {
        return searchPrefix(prefix) != null;
    }
    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;
    }
    //定义新方法,判断某个单词是否在前缀树中存在前缀,并返回前缀
    public String getPrefixFromWord(String word) {
        Trie node = this;
        String res = "";
        for (int i = 0; i < word.length(); i++) {
            //判断前缀树中是否有一个前缀,该前缀正好是该单词的前缀
            char ch = word.charAt(i);
            int index = ch - 'a';
            if (node.children[index] == null) {
                return word;
            }
            res += ch;
            node = node.children[index];
            if (node.isEnd == true) {
                return res;
            }
        }
        return word;
    }
}

Hash表实现:

class Solution {
    public String replaceWords(List<String> dictionary, String sentence) {
        Set<String> dictionarySet = new HashSet<String>();
        for (String root : dictionary) {
            dictionarySet.add(root);
        }
        String[] words = sentence.split(" ");
        for (int i = 0; i < words.length; i++) {
            String word = words[i];
            for (int j = 0; j < word.length(); j++) {
                if (dictionarySet.contains(word.substring(0, 1 + j))) {
                    words[i] = word.substring(0, 1 + j);
                    break;
                }
            }
        }
        return String.join(" ", words);
    }
}

作者:LeetCode-Solution
链接:https://leetcode.cn/problems/UhWRSj/solution/ti-huan-dan-ci-by-leetcode-solution-9reh/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值