单词的压缩编码
难度:
标签:
题目描述
English description is not available for the problem. Please switch to Chinese.
代码结果
运行时间: 46 ms, 内存: 16.4 MB
/*
* 思路:
* 1. 对单词数组进行排序,按照单词的逆序排列
* 2. 使用一个Set存储所有单词的后缀
* 3. 遍历排序后的单词数组,检查每个单词是否在Set中,如果不在则将该单词的所有后缀加入Set,并增加编码长度
* 4. 最后得到的编码长度即为最小助记字符串的长度
*/
import java.util.*;
import java.util.stream.Collectors;
public class MinimumLengthEncoding {
public int minimumLengthEncoding(String[] words) {
// 对单词数组进行排序,按照单词的逆序排列
List<String> sortedWords = Arrays.stream(words)
.sorted((a, b) -> new StringBuilder(b).reverse().toString().compareTo(new StringBuilder(a).reverse().toString()))
.collect(Collectors.toList());
Set<String> set = new HashSet<>();
final int[] result = {0};
// 遍历排序后的单词数组
sortedWords.forEach(word -> {
if (!set.contains(word)) {
// 如果Set中不包含当前单词,则将该单词的所有后缀加入Set
for (int i = 0; i < word.length(); i++) {
set.add(word.substring(i));
}
// 增加编码长度
result[0] += word.length() + 1;
}
});
return result[0];
}
public static void main(String[] args) {
MinimumLengthEncoding solution = new MinimumLengthEncoding();
String[] words = {"time", "me", "bell"};
System.out.println(solution.minimumLengthEncoding(words)); // 输出 10
}
}
解释
方法:
这个题解的核心思路是利用排序和字符串后缀的比较来确定哪些单词是其他单词的后缀。首先,将每个单词逆序,然后对这些逆序后的单词进行排序。排序后,如果某个单词是另一个单词的前缀(由于单词已经逆序,实际上检查的是后缀),则这个单词可以被完全包含在另一个单词的编码中。遍历排序后的单词列表,如果一个单词不是下一个单词的前缀,则它需要单独计入最终的编码字符串中,计算长度时要加上一个字符的空间来放置分隔符'#'。
时间复杂度:
O(n log n)
空间复杂度:
O(nk)
代码细节讲解
🦆
为什么选择将单词逆序后再进行排序,而不是直接排序原始单词?
▷🦆
在排序逆序单词的过程中,如何处理长度不同但内容相似的单词,例如单词 'a' 和 'ba'?
▷🦆
题解中提到如果一个单词是下一个单词的前缀则可以被包含,这种方法是否考虑了多个连续单词可能相互包含的情况?
▷