Unique Word Abbreviation LC解题记录

398 查看

题目内容

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%高一些。

最后再说两句

距离上一篇文章过了一段时间了,这段时间搬家再适应新环境,解决心理问题。从这一篇开始将会继续保持更新进度。