题目内容
An abbreviation of a word follows the form <first letter><number><last letter>. Below are some examples of word abbreviations:
a) it --> it (no abbreviation)
1
b) d|o|g --> d1g
1 1 1
1---5----0----5--8
c) i|nternationalizatio|n --> i18n
1
1---5----0
d) l|ocalizatio|n --> l10n
Assume you have a dictionary and given a word, find whether its abbreviation is unique in the dictionary.
A word abbreviation is unique if no other word from the dictionary has the same abbreviation.
Example:
Given dictionary = [ "deer", "door", "cake", "card" ]
isUnique("dear") -> false
isUnique("cart") -> true
isUnique("cane") -> false
isUnique("make") -> true
这题也是锁住的,通过率只有15%左右。这让我不得其解,为啥一道easy级别的题目会有如此低的Pass?是人性的扭曲还是道德的沦丧,美国没有《走近科学》,只能自己动手写。
解决思路
这题比较考察洋文水平,扫一眼要求很容易看出,应该把已有的dictionary的缩略词都缩出来,存到一个地方,刚开始用了个Set。再调用isUnique的时候,用目标字符串压缩后和Set里面的元素做比较。有相同的就返回false,没有就是true。
但是,
后来出了问题,因为目标词可能和字典里面的词一致,比如字典里只有有"hello",调用isUnique检查hello的时候,应该返回true,因为没有其他词和h3o一样了。另外,字典里面只有两个hello的时候,也是返回true。所以这题的关键点在于『no other word』
code
public class ValidWordAbbr {
Map<String,ArrayList<String>> map = new HashMap<>();
public ValidWordAbbr(String[] dictionary) {
//每个词都轮一遍
for (String str : dictionary) {
String abrv = abbrev(str);
if (!map.containsKey(abrv)){
ArrayList<String> list = new ArrayList<>();
list.add(str);
map.put(abrv,list);
}
else {
ArrayList<String> list = map.get(abrv);
//这里的判断是过滤相同的词
if (!list.contains(str)) list.add(str);
map.put(abrv, list);
}
}
}
public boolean isUnique(String word) {
String abrv = abbrev(word);
if (map.containsKey(abrv)){
//先看相同压缩串是不是代表多个词,一旦多了那肯定不行
if (map.get(abrv).size() > 1) return false;
//如果只有1个,那就对比一下这两个词是不是一样的,一样就行
else if (map.get(abrv).get(0).equals(word)) return true;
return false;
}
//其他情况肯定是都行。
return true;
}
//把字符串变成压缩串
public String abbrev(String word){
if(word == null || word.length() < 3){
return word;
}
//把头,数字,尾巴连起来。
StringBuilder sb = new StringBuilder();
int len = word.length()-2;
String slen = String.valueOf(len);
sb.append(word.charAt(0));
sb.append(slen);
sb.append(word.charAt(word.length()-1));
return sb.toString();
}
//做测试用
public static void main(String[] args) {
String[] test = {"hello", "a", "a"};
ValidWordAbbr vwa = new ValidWordAbbr(test);
System.out.print(vwa.isUnique("a"));
}
}
复杂度分析
截至目前,我还不太清楚这种设计题会不会特别在意复杂度,可能更注重corner case。这题遍历一遍字典就可以了,所以复杂度是O(n)。需要注意的是no other word这个说法,让我多付出了两次submit的代价,不过还好比15%高一些。
最后再说两句
距离上一篇文章过了一段时间了,这段时间搬家再适应新环境,解决心理问题。从这一篇开始将会继续保持更新进度。