Java每日一题——>面试题 10.02. 变位词组

Posted stormzhuo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java每日一题——>面试题 10.02. 变位词组相关的知识,希望对你有一定的参考价值。

题目

这是LeetCode上的 [10.02,变位词组],难度为 [中等]

编写一种方法,对字符串数组进行排序,将所有变位词组合在一起。变位词是指字母相同,但排列不同的字符串。

示例

输入: ["eat", "tea", "tan", "ate", "nat", "bat"],
输出:
[
  ["ate","eat","tea"],
  ["nat","tan"],
  ["bat"]
]

说明:

  • 所有输入均为小写字母。
  • 不考虑答案输出的顺序。

思路分析

根据题意同一个变位词组的每个单词中的字符及每个字符出现的次数都相同,但顺序不同,因此同一组变位词中的字符串具备相同点,可以使用相同点作为一组变位词的标志

遍历每个字符串,对于每个字符串,得到该字符串所在的一组变位词的标志,将当前字符串加入该组变位词的列表中。

题解1(将单词映射到质数)

我们可以把字符串的字符映射到质数中,因为在同一个变位词组中,虽然字符顺序不同,但它们的每个字符对应的质数的乘积是相同的,因此就找到了同一个变位词组的共同点

我们可以创建一个哈希表,哈希表的键存放字符串所有字符的质数的乘积,值存放变位词组

代码实现

class Solution 
    public List<List<String>> groupAnagrams(String[] strs) 
        // 存放所有小写英文字符对应的质数,第一个映射字符a,以此类推
        int[] hash = 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,
                67,71,73,79,83,89,97,101;
        // 创建哈希表,键存放质数的乘积,值存放变位词组
        HashMap<Long, List<String>> groups = new HashMap<>();
        // 遍历单词数组
        for (String str : strs) 
            // 存放质数乘积
            Long wordHash = 1L;
            // 遍历单词
            for (int i = 0; i < str.length(); i++) 
                // 把单词的所有字母对应的质数进行累乘
                wordHash *= hash[str.charAt(i) - 'a'];
            
            // 若哈希表不存在质数乘积的值,则以此质数乘积为键创建一个空的变位词组
            groups.putIfAbsent(wordHash, new ArrayList<>());
            // 以质数乘积为键获取变位词组添加一个单词
            groups.get(wordHash).add(str);
        
        return new ArrayList<>(groups.values());
    

复杂度分析

假设输入n个单词,平均每个单词有m个字符

时间复杂度

需要遍历每个单词,遍历每个单词过程中需要遍历每个单词的字符,故时间复杂度为O(nm)

空间复杂度

假设n个单词可以组合成k个变位词组,哈希表会随着变位词组的个数的增多而扩容,故空间复杂度为O(k)

缺点: 当单词特别长时,质数的乘积可以会超过Long的取值,溢出

题解2(映射到同一个单词,排序)

我们还可以把一组变位词组映射到同一个单词中,例如对同一组变位词的每一个字符串的字符进行排序可以得到同一个单词,因此也就找到了同一个变位词组的共同点

我们可以创建一个哈希表,哈希表的键存放字符串排序后的单词,值存放变位词组

代码实现

class Solution 
    public List<List<String>> groupAnagrams(String[] strs) 
         /* 创建一个哈希表,键存放每个变位词组的每个单词排序后的单词
        * 值存放每个每个变为词组*/
        HashMap<String, List<String>> groups = new HashMap<>();
        // 遍历单词数组
        for (String str : strs) 
            // 单词字符串转换为字符数组
            char[] chars = str.toCharArray();
            // 对单词字符数组排序,同一个变位词组的单词排序的单词都相等
            Arrays.sort(chars);
            // 把排序后的单词字符数组转换为字符串
            String sorted = new String(chars);
            // 若哈希表不存在排序后的单词字符串,则创建一个空的变位词组
            groups.putIfAbsent(sorted, new ArrayList<>());
            // 根据排序后的单词字符串作为键获取变位词组,并把单词字符串添加到变位词组中
            groups.get(sorted).add(str);
        
        return new ArrayList<>(groups.values());
    

复杂度分析

假设输入n个单词,每个单词平均有m个字符

时间复杂度

由于需要对每个单词进行排序,而排序单词的时间为O(mlogm),需要排序每个单词,故总的时间复杂度为O(nmlogm)

空间复杂度

随着排序后的不同单词数目的增多,即变位词组也会不断的增多,哈希表也会不断的扩容。假设n个单词可以组成k个变位词组,则空间复杂多为O(k)

以上是关于Java每日一题——>面试题 10.02. 变位词组的主要内容,如果未能解决你的问题,请参考以下文章

Java每日一题——>面试题 10.02. 变位词组

《LeetCode之每日一题》:94.面试题 10.02. 变位词组

Java每日一题——>剑指 Offer II 032. 有效的变位词

Java每日一题——>剑指 Offer II 032. 有效的变位词

Java每日一题——>剑指 Offer II 032. 有效的变位词

面试题 10.02. 变位词组