单词的压缩编码(中等)字典树/前缀树/Trie数

题目:
给定一个单词列表,我们将这个列表编码成一个索引字符串 S 与一个索引列表 A。
例如,如果这个列表是 [“time”, “me”, “bell”],我们就可以将其表示为 S = “time#bell#” 和 indexes = [0, 2, 5]。
对于每一个索引,我们可以通过从字符串 S 中索引的位置开始读取字符串,直到 “#” 结束,来恢复我们之前的单词列表。
那么成功对给定单词列表进行编码的最小字符串长度是多少呢?

示例:
输入: words = [“time”, “me”, “bell”]
输出: 10
说明: S = “time#bell#” , indexes = [0, 2, 5] 。

来源:力扣(LeetCode)

刚开始我的思路是遍历整个字符串数组,如果后一个是前一个的后缀那么长度不变,否则,总长度+1再加上后一个单词的长度。
如果但看示例,这样的想法是没有任何问题的,但关键是如果长度短的在前,长的在后,便会出错。

所以在查阅过后,我学到了字典树这种数据结构。

即一个节点内包括一个长度为26的节点数组。
每个节点在数组中的位置代表a,b,c…

而本题,考虑的是后缀,所以我们将每一个单词从尾到头加入字典树。
这样总长度即是所有叶子结点到根节点的长度之和。
注意:单词加入字典树的顺序为从长到短。

代码:

class Solution {
    public int minimumLengthEncoding(String[] words) {
        if(words.length == 0)
            return 0;
        if(words[0].length() == 1)
            return words[0].length()+1;
        StringBuffer sb = new StringBuffer();
        Arrays.sort(words,new Comparator<String>(){
            public int compare(String s1,String s2){
                if(s1.length() == s2.length())
                    return 0;
                return s1.length()>s2.length()?-1:1;
            }
        });
        int res = 0;
        TreeNode root = new TreeNode(0);
        for(String s:words)
            res += root.insert(s);
        return res;
    }
}
class TreeNode{
    public int val;
    public TreeNode[]child;
    public TreeNode(int x){
        child = new TreeNode[26];
        val = x;
    }
    public int insert(String word){
        boolean isNew = false;
        TreeNode t = this;
        for(int i = word.length()-1;i>=0;i--){
            if(t.child[word.charAt(i)-'a'] == null){
                isNew = true;
                t.child[word.charAt(i)-'a'] = new TreeNode(word.charAt(i)-'a');
            }
            t = t.child[word.charAt(i)-'a'];
        }
        return isNew?word.length()+1:0;
    }
}

你可能感兴趣的:(Java,算法,LeetCode)