题目链接
思路
- 注意这道题求的是编码总长度。。。。。不是编码的字符串是啥/(ㄒoㄒ)/~~(一开始木有仔细看题)
- 读题后可以发现,如果一个单词是另一个单词的后缀,那么就可以不用重复编码。比如time me,那么他们只需要编码time#即可,但是对于time ti就不可以,就得编码为ti#time#
- 具体的编码长度可以转化为前缀树的深度问题
- 但是问题是如果用前缀树表示,time ti最终的深度就是4,因为ti是time的前缀,那么既然后缀可以不用重复编码,我们可以在建立前缀树的时候把单词反序建立(注意代码中是如何反序遍历字符串建树的),这样ti time建出来的前缀树就是i t/e m i t 最终深度就为6
- 因为最终每一个子字符串都要在结尾加一个#,所以可以把根节点root作为1层,这样遍历出来的 i t深度就为3
- 判断是否是叶子节点的方式为:如果children数组每一个元素都为null,那么就是叶子结点
class Solution {
class TrieNode {
TrieNode[] children;
TrieNode() {
children = new TrieNode[26];
}
}
private TrieNode root;
private int height;
void buildTree(String[] words) {
root = new TrieNode();
for (String word : words) {
TrieNode cur = root;
for (int i = word.length() - 1; i >= 0; i--) {
if (null == cur.children[word.charAt(i) - 'a'])
cur.children[word.charAt(i) - 'a'] = new TrieNode();
cur = cur.children[word.charAt(i) - 'a'];
}
}
}
void dfs(TrieNode root, int nowHeight) {
if (null == root)
return;
boolean flag = true;
for (TrieNode node : root.children) {
if (null != node) {
flag = false;
dfs(node, nowHeight + 1);
}
}
if (flag)
height += nowHeight;
}
public int minimumLengthEncoding(String[] words) {
buildTree(words);
height = 0;
dfs(root, 1);
return height;
}
}