剑指 Offer II 065. 最短的单词编码(中等 字典树 字符串 数组)

剑指 Offer II 065. 最短的单词编码

单词数组 words 的 有效编码 由任意助记字符串 s 和下标数组 indices 组成,且满足:

words.length == indices.length
助记字符串 s 以 ‘#’ 字符结尾
对于每个下标 indices[i] ,s 的一个从 indices[i] 开始、到下一个 ‘#’ 字符结束(但不包括 ‘#’)的 子字符串 恰好与 words[i] 相等
给定一个单词数组 words ,返回成功对 words 进行编码的最小助记字符串 s 的长度 。

示例 1:

输入:words = [“time”, “me”, “bell”]
输出:10
解释:一组有效编码为 s = “time#bell#” 和 indices = [0, 2, 5] 。
words[0] = “time” ,s 开始于 indices[0] = 0 到下一个 ‘#’ 结束的子字符串,如加粗部分所示 “time#bell#”
words[1] = “me” ,s 开始于 indices[1] = 2 到下一个 ‘#’ 结束的子字符串,如加粗部分所示 “time#bell#”
words[2] = “bell” ,s 开始于 indices[2] = 5 到下一个 ‘#’ 结束的子字符串,如加粗部分所示 “time#bell#”
示例 2:

输入:words = [“t”]
输出:2
解释:一组有效编码为 s = “t#” 和 indices = [0] 。

提示:

1 <= words.length <= 2000
1 <= words[i].length <= 7
words[i] 仅由小写字母组成

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/iSwD2y
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

分析

本题的目标是得到最短的编码,按照题目要求,两个单词的末尾相同可以并到同一个单词中,因此我们可以倒序遍历字符串的字母,从末尾开始存储字符串前缀构造前缀树,然后利用dfs遍历前缀树记录所有符合条件的路径长度和。
进行dfs的时候,因为对于前缀树的一棵未被记录的子树来说,末尾需要添加#字符,所以提前设置好子树的长度length为1,只需要在此基础上加上子树长度即可;还需要注意的是最终返回的答案要用数组储存,因为基本类型的变量在方法中传递的是形参,作为返回值的实参不会改变。

题解(Java)

class Solution {
    static class TrieNode {
        public TrieNode[] children;

        public TrieNode() {
            children = new TrieNode[26];
        }
    }

    public int minimumLengthEncoding(String[] words) {
        TrieNode root = new TrieNode();
        for (String word : words) {
            TrieNode node = root;
            for (int i = word.length() - 1; i >= 0; i--) {
                char ch = word.charAt(i);
                if (node.children[ch - 'a'] == null) {
                    node.children[ch - 'a'] = new TrieNode();
                }
                node = node.children[ch - 'a'];
            }
        }

        int[] ans = {0};
        dfs(root, ans, 1);
        return ans[0];
    }

    private void dfs(TrieNode root, int[] ans, int length) {
        boolean isLeaf = true;//作为子树是否到达末尾的条件。
        for (TrieNode child : root.children) {
            if (child != null) {
                isLeaf = false;
                dfs(child, ans, length + 1);
            }
        }

        if (isLeaf) {
            ans[0] += length;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值