如何在500w个单词中统计特定前缀的单词有多少个?
如何在500w个单词中统计特定前缀的单词有多少个?
今天小史去了一家在线英语培训公司面试了。
简单的自我介绍后,面试官给了小史一个问题。
题目:我有500w个单词,你帮忙设计一个数据结构来进行存储,存好之后,我有两个需求。
1、来了一个新的单词,需要判断是否在这500w个单词中
2、来了一个单词前缀,给出500w个单词中有多少个单词是该前缀
小史这次没有不假思索就给出回答,他学会了深沉。
小史回忆起吕老师之前教他的 bitmap 算法。
小史心想:bitmap可以判断一个数是否在40亿个int32数中,其核心是每一个数映射成一个位,同时申请的bit位数覆盖了整个int32的值域。
小史在纸上算了半天,终于开口了。
小史:好的,我用bitmap来做第一问。我把每一个字符串映射成一个位。比如,a是第1位,b是第2位,z是第26位,aa是第27位,ab是第28位,以此类推。英文一共26个字母,我算了一下,6个字符长度的单词总共有26的6次方个,需要占26的6次方个位,大概300M
小史:建立数据结构的时候,排序需要花掉nlg(n),排序时字符串比较花掉m,时间一共mnlg(n)。查找的话用二分,就是mlg(n)了。空间是mn。
一分钟过去了。
【请教大神】
回到学校,小史把面试情况和吕老师说了一下。
s
吕老师:你想想,a到z这26个字母中,可能只有a和i两个是单词,其他都不是,所以你的bitmap大量空间都被浪费了。这种情况你搞个hashset没准还更省一点。
【树形结构解难题】
小史:哦,这确实是节省了空间,如果要找单词interest,那么就找根节点了,如果是找单词interesting,那么就从根节点往下走,再把沿路的字母们都拼起来就行了。
(注:这里说的in不是单词,指的是in不是500w单词中的单词)
吕老师还没说完,小史就打断了他。
找单词interest:
找前缀为inter的所有单词:
遍历以前缀节点为根结点的一棵树,就能统计出前缀为inter的所有单词有多少个。
【字典树】
小史:节点中增加一个变量用于计数,在添加节点的时候,就把相应的计数+1
理解了算法之后,小史的代码写起来也是非常快,不一会儿就写好了:
DictionaryTree.java
Main.java
运行结果
【字典树的应用】
小史:我想想啊,大量字符串的统计和查找应该就可以用字典树吧?字符串前缀的匹配也可以用,像咱们搜索常见的autoComplete控件是不是就可以用?
评论(2)
没有文章中的那么麻烦吧
class Solution {
public String longestPalindrome(String s) {
if (s null || s.length() < 1) { return “”;}
int begin = 0, end = 0;
for (int i = 0; i < s.length(); i++) {
// 不同的中心点
int length1 = this.findFromCenter(s, i, i);
int length2 = this.findFromCenter(s, i, i + 1);
int len = Math.max(length1, length2);
if (len > end – begin) {
begin = i – (len – 1) / 2;
end = i + len / 2;
}
}
return s.substring(begin, end + 1);
}
private int findFromCenter(String str, int left, int right) {
int newL = left;
int newR = right;
while (newL >= 0 && newR < str.length() && str.charAt(newL) == str.charAt(newR)) {
newL--;
newR++;
}
return newR - newL - 1;
}
}