527. Word Abbreviation

Hard
Given an array of n distinct non-empty strings, you need to generate minimal possible abbreviations for every word following rules below.

Begin with the first character and then the number of characters abbreviated, which followed by the last character.
If there are any conflict, that is more than one words share the same abbreviation, a longer prefix is used instead of only the first character until making the map from word to abbreviation become unique. In other words, a final abbreviation cannot map to more than one original words.
If the abbreviation doesn't make the word shorter, then keep it as original.

Example:

Input: ["like", "god", "internal", "me", "internet", "interval", "intension", "face", 
"intrusion"]
Output: ["l2e","god","internal","me","i6t","interval","inte4n","f2e","intr4n"]

Note:
Both n and the length of each word will not exceed 400.
The length of each word is greater than 1.
The words consist of lowercase English letters only.
The return answers should be in the same order as the original array.

据说是G家的一道题,听高频题听到的。听完之后写起来真的不难,至少逻辑上是很直接的,只是注意很多小细节。题目很长,简化下来就是:

  • 保留头尾,缩中间
  • 缩了比原串长或者相等,就不缩了
  • 如果有重复,则头部多保留一位,继续缩,直到没重复

亮点:

  • 用prefix[] 来记录保留前几个字母,缩中间,保留最后一个字符;
  • 用hashmap来记录每个缩后的字符串出现的次数,如果大于一次,则说明又重复,需要继续缩,这里注意一个Java8的新写法:`getOrDefault(Object o, V defultValue), 意思就是如果map里面有这个key,就返回这个key的value, 如果没有这个key,就返回默认值0;
  • while(true)这种写法,就是forever enter while loop 直到你主动break出去,这里我们如果遇到重复,虽然已经继续收缩了,但还是得set unique = false让while loop继续遍历,因为我们不直到下一步会不会继续得到缩写后相同的字符串.
  • getAbbr(String s, int p)也把复杂的问题巧妙地简单化处理了,直接用substring就很好写,并且也满足了题目条件,只要保留的头部长度大于或者等于原串总长度 - 2, 就不用缩了,反正缩了也不会短,这个特点需要自己观察。
class Solution {
    public List wordsAbbreviation(List dict) {
        List res = new ArrayList<>();
        Map count = new HashMap<>();
        int[] prefix = new int[dict.size()];
        for (int i = 0; i < dict.size(); i++){
            prefix[i] = 1;
            res.add(getAbbr(dict.get(i), 1));
            count.put(res.get(i), count.getOrDefault(res.get(i), 0) + 1);  
        }
        //this means we will enter while loop forever until you break out
        while (true){
            boolean unique = true;
            for (int i = 0; i < dict.size(); i++){
                if (count.get(res.get(i)) > 1){
                    prefix[i]++;
                    res.set(i, getAbbr(dict.get(i), prefix[i]));
                    count.put(res.get(i), count.getOrDefault(res.get(i), 0) + 1);  
                    unique = false;
                }
            }
            if (unique){
                break;
            }
        }
        return res;
    }
    
    private String getAbbr(String s, int p){
        if (p >= s.length() - 2){
            return s;
        }        
        s = s.substring(0, p) + (s.length() - 1 - p) + s.charAt(s.length() - 1);
        return s;
    }
}

你可能感兴趣的:(527. Word Abbreviation)