zoukankan      html  css  js  c++  java
  • leetcode527

    Given an array of n distinct non-empty strings, you need to generate minimal possible abbreviations for every word following rules below.
    1. Begin with the first character and then the number of characters abbreviated, which followed by the last character.
    2. 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.
    3. 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:
    1. Both n and the length of each word will not exceed 400.
    2. The length of each word is greater than 1.
    3. The words consist of lowercase English letters only.
    4. The return answers should be in the same order as the original array.
     
    模拟法。Map辅助。
    写一个子方法,能根据需求的prefix长度来把s做转换后传回。
     
    法1.用Map<String, Integer>存储每个abbr当前有出现过几次,提供查询。具体的每个下标当前的缩进结果放在ans数组里,当前缩进几格放在prefix数组里。每轮检查当前result[i]合格了没,要是返回的count>1那就是不合格的,得增大prefix继续更新。要是某轮后没有任何更新就跳出循环。
    细节
    1.每轮更新放大prefix做更新后不要降级老string的计数。解释:intension和intrusion最后转化成的是inte4n和intr4n,而不是inte4n和int3n,是不是奇怪这两个已经不一样了为什么不让一个进一步呢?因为题目有说a final abbreviation cannot map to more than one original words,而int3n同时map到那两个字符串了不行的。如果你代码里让老string的计数降级,那你可能遍历到intr4n的时候就发现int3n的count已经变成1了,对字符串intrusion它就不做从int3n到intr4n的转变了,那就错了。
    2.题目说的少缩进一些的方法不是每次均匀往中间少缩两格放出两个字母,只是prefix缩一格进去,非对称。
    3.存放中间结果和每个string当前prefix长度用的array而不是list,因为list不能在长度还未到达的时候set某一个后面的位置。
    4.array -> list的API:Collections.addAll(list, array)。
     
    法2. 用Map<String, List<Integer>>存储每个缩写一定程度后的abbr对应的初始字符的下标。当map的大小和输入list一致,就说明每个abbr都是独立的了,达成目标。如果还没有成功的话,就从那些不合格的entry取到初始字符,再进一步留多一些prefix。
    细节:每次要开新map: 你不能在遍历keySet()的时候又给keySet()插入删除key值,这是逻辑不对而且编译会报错ConcurrentModificationException。 

    实现1:

    class Solution {
        public List<String> wordsAbbreviation(List<String> dict) {
            if (dict == null || dict.size() == 0) {
                return new ArrayList<String>();
            }
            
            int[] prefix = new int[dict.size()];
            String[] result = new String[dict.size()];
            Map<String, Integer> count = new HashMap<>();
            
            // initialization
            for (int i = 0; i < dict.size(); i++) {
                prefix[i]++;
                String abbr = abbreviate(dict.get(i), prefix[i]);
                result[i] = abbr;
                count.put(abbr, count.getOrDefault(abbr, 0) + 1);
            }
            
            boolean hasDup = true;
            while (hasDup) {
                hasDup = false;
                for (int i = 0; i < dict.size(); i++) {
                    if (count.get(result[i]) > 1) {
                        hasDup = true;
                        prefix[i]++;
                        String newAbbr = abbreviate(dict.get(i), prefix[i]);
                        result[i] = newAbbr;
                        count.put(newAbbr, count.getOrDefault(newAbbr, 0) + 1);
                    }
                }
            }
            
            // P3: 生成List
            List<String> resultList = new ArrayList<>();
            Collections.addAll(resultList, result);
            return resultList;
        }
        
        private String abbreviate(String s, int prefix) {
            if (s.length() - prefix - 1 <= 1) {
                return s;
            } else {
                // P2: 注意题意不是每次均匀往中间缩两格,只是prefix缩一格进去。
                return s.substring(0, prefix) + (s.length() - prefix - 1) + s.substring(s.length() - 1, s.length());
            }
        }
    }

    实现2:

    class Solution {
        public List<String> wordsAbbreviation(List<String> dict) {
            if (dict == null || dict.size() == 0) {
                return new ArrayList<String>();
            }
            
            Map<String, List<Integer>> strIdxes = new HashMap<>();
            int prefix = 1;
            
            // initialization
            for (int i = 0; i < dict.size(); i++) {
                String abbreved = abbreviate(dict.get(i), prefix);
                strIdxes.putIfAbsent(abbreved, new ArrayList<>());
                strIdxes.get(abbreved).add(i);
            }
            
            while (strIdxes.size() < dict.size()) {
                prefix++;
                System.out.println(prefix);
                // P1: 每次要开新map的原因: 你不能在遍历keySet()的时候又给keySet()插入删除key值,这是逻辑不对而且编译会报错ConcurrentModificationException。
                Map<String, List<Integer>> newMap = new HashMap<>();
                for (String s : strIdxes.keySet()) {
                    List<Integer> indexes = strIdxes.get(s);
                    if (indexes.size() == 1) {
                        newMap.put(s, indexes);
                        continue;
                    }
                    for (int index : indexes) {
                        String newAbbreved = abbreviate(dict.get(index), prefix);
                        newMap.putIfAbsent(newAbbreved, new ArrayList<>());
                        newMap.get(newAbbreved).add(index);
                    }
                }
                strIdxes = newMap;
            }
            
            // P3: 生成List
            String[] resultArr = new String[dict.size()];
            for (String s : strIdxes.keySet()) {
                resultArr[strIdxes.get(s).get(0)] = s;
            }
            List<String> result = new ArrayList<>();
            Collections.addAll(result, resultArr);
            return result;
        }
        
        private String abbreviate(String s, int prefix) {
            if (s.length() - prefix - 1 <= 1) {
                return s;
            } else {
                // P2: 注意题意不是每次均匀往中间缩两格,只是prefix缩一格进去。
                return s.substring(0, prefix) + (s.length() - prefix - 1) + s.substring(s.length() - 1, s.length());
            }
        }
    }
  • 相关阅读:
    【华为云技术分享】手把手教你如何在ARM上源码编译Redis
    【华为云技术分享】Linux内核编程环境 (2)
    华为云MySQL 8.0正式商用,全新增强版开源利器强势来袭
    【转载】Mysql删除所有表不删除数据库方法
    【转载】使用Sublime Text 3的HTML-CSS-JS Prettify插件格式化代码
    【转载】Node.js学习笔记之一
    jquery分页插件pagination.js的使用
    Windows平台下搭建Git服务器
    js实现返回页面顶部
    交换机的级联和堆叠
  • 原文地址:https://www.cnblogs.com/jasminemzy/p/9612919.html
Copyright © 2011-2022 走看看