【哈希】【中等】字母异位词分组

题目

给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。

示例 1:

  • 输入: strs = "eat", "tea", "tan", "ate", "nat", "bat"
  • 输出: \["bat","nat","tan","ate","eat","tea"]

解释:

在 strs 中没有字符串可以通过重新排列来形成 "bat"。

字符串 "nat" 和 "tan" 是字母异位词,因为它们可以重新排列以形成彼此。

字符串 "ate" ,"eat" 和 "tea" 是字母异位词,因为它们可以重新排列以形成彼此。

示例 2:

  • 输入: strs = ""

  • 输出: \[""]
    示例 3:

  • 输入: strs = "a"

  • 输出: \["a"]
    提示:

  • 1 <= strs.length <= 104

  • 0 <= strsi.length <= 100

  • strsi 仅包含小写字母

解法1:

 利用Map数据结构,每次数组循环进行判别strs = "eat", "tea", "tan", "ate", "nat", "bat"

str char数组 Map-key Map-value(list)
eat aet aet eat
tea aet 判别已存在(aet) tea
tan ant ant tan
ate aet 判别已存在(aet) ate
nat ant 判别已存在(ant) nat
bat abt abt bat
java 复制代码
class Solution {
    public static List<List<String>> groupAnagrams(String[] strs) {
        Map<String, List<String>> map = new HashMap<>();
        for (String str : strs) {
            char[] chars = str.toCharArray();
            Arrays.sort(chars);//排序
            String key = new String(chars);
            //当前数组对应的sort串没有被存放过
            if (map.containsKey(key)) {
                map.get(key).add(str);
            }
            else {
                List<String> list = new ArrayList<>();
                list.add(str);
                map.put(key, list);
                //map.put(Arrays.toString(chars), list);
            }
        }
        return new ArrayList<>(map.values());
    }
}

注:不能是map.put(Arrays.toString(chars), list);注意区分new String()和Arrays.toString()

->toString()、Arrays.toString()、new String()区别

  • toString():获取对象的字符串表示,Object 类中定义的方法,所有 Java 对象都继承。被子类重写以返回有意义的字符串描述。返回 "类名@哈希码十六进制"
java 复制代码
Integer num = 42;
System.out.println(num.toString());  // "42"

int[] arr = {1,2,3};
System.out.println(arr.toString());  // [I@4eec7777(数组未重写,所以是 Object 的默认实现)
  • Arrays.toString():将数组转换为友好的字符串,java.util.Arrays 类的静态方法,专门用于将数组(基本类型或对象数组)转换为其内容的字符串表示。返回格式为 元素1, 元素2, ...,例如 "1, 2, 3"。
java 复制代码
int[] numbers = {1, 2, 3};
System.out.println(Arrays.toString(numbers));  // [1, 2, 3]
System.out.println(numbers.toString());        // [I@4eec7777

char[] chars = {'a', 'b', 'c', 'd', 'e', 'f'};
System.out.println(Arrays.toString(chars));    // [a, b, c, d, e, f]
System.out.println(chars.toString());          // [C@3b07d329
  • new String():显式创建字符串对象,本质是 String 类的构造方法,用于在堆内存中创建一个新的 String 对象。
    • new String():创建一个空字符串 ""。
    • new String(char\[\] arr):根据字符数组创建新字符串。
    • new String(byte\[\] bytes):根据字节数组(按平台默认字符集解码)创建字符串。

解法2:

核心方法:延续排序标识分组核心逻辑 + Java8流式编程简化实现,与第一次解答的核心算法完全一致,通过Java8的流式API和集合收集器替代手动的for循环与哈希表操作,大幅精简代码行数,让代码更优雅、更简洁。

java 复制代码
class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        return new ArrayList<>(
            Arrays.stream(strs)
                .collect(Collectors.groupingBy(
                    str -> {
                        char[] chars = str.toCharArray();
                        Arrays.sort(chars);
                        return new String(chars);
                    }
                ))
                .values()
        );
    }
}