LeetCode字母异位词分组两种解法疑问:为何第二种无法得到正确结果?
字母异位词分组解法失效原因分析
给定字符串数组strs,需将字母异位词分组后返回(顺序不限)。以下是两种Java实现,其中解法1可正确分组,解法2最终返回空集合,其失效原因如下:
解法1(正确)
public List<List<String>> groupAnagrams(String[] strs) { HashMap<String, List<String>> hm = new HashMap<>(); for(String st : strs){ char[] arr = st.toCharArray(); Arrays.sort(arr); String cannonical = new String(arr); if(!hm.containsKey(cannonical)){ hm.put(cannonical, new LinkedList<String>()); } hm.get(cannonical).add(st); } return new LinkedList<>(hm.values()); }
解法2(错误)
public List<List<String>> groupAnagrams(String[] strs) { HashMap<String, List<String>> hm = new HashMap<>(); for(String st : strs){ char[] arr = st.toCharArray(); Arrays.sort(arr); String cannonical = new String(arr); hm.getOrDefault(cannonical, new LinkedList<String>()).add(st); } return new LinkedList<>(hm.values()); }
失效核心原因
问题出在getOrDefault方法的使用逻辑上:
getOrDefault的作用是:如果Map中存在指定键,返回对应的值;如果不存在,返回你传入的默认对象,但不会自动将这个默认对象存入Map。- 解法2中,当
cannonical作为键不存在于HashMap时,getOrDefault会新建一个LinkedList,你给这个临时列表添加了元素,但这个列表从未被放入HashMap中。添加操作结束后,这个临时列表就成了无引用的垃圾对象,HashMap始终没有被写入任何键值对,最终返回的hm.values()自然是空集合。 - 解法1的逻辑是先判断键是否存在,不存在则手动将新列表存入Map,后续的
add操作是对Map中已存在的列表进行修改,因此能正确分组。
如果想用类似简化写法,应该使用computeIfAbsent方法,它会在键不存在时自动创建并插入默认值,同时返回该值,后续的add操作会直接作用于Map内的列表:
hm.computeIfAbsent(cannonical, k -> new LinkedList<>()).add(st);
内容的提问来源于stack exchange,提问作者Paurab Bhattacharjee
相关产品推荐
相关产品推荐

