leetcode 49. 字母异位词分组 java (看得懂的详细解析)

博客介绍了如何解决LeetCode的49题,即字母异位词分组问题。提供了两种解决方案,一种是通过排序字符串比较,另一种是利用质数映射进行判断。虽然第二种方法时间复杂度较低,但可能因字符串过长导致乘积溢出,此时需要使用第一种方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:
给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。

示例:

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

说明:

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

解析:
本题要求将所有的字母异位词放在一起,我们问题的关键在于如何求两个或者多个字符串属于字母异位词。本文介绍两种方法,时间复杂度都很低,稍快的一种有一点缺陷,但是测试用例都通过了。

第一种方式是将这两个或者多个字符串中的字符排序,然后看排序后的字符串是不是相同的,如果是,那么就属于字母异位词,否则就不是。

第二种方式是利用了质数的性质,只有同样的几个质数相乘才能得到同样的乘积,我们创建了一个长度为26的质数数组,以字符串中每个字符与’a’的距离来将字符映射到不同的质数上,将一个字符串中的所有字符表示的质数相乘,就可以将最终的乘积作为判断两个或者多个字符串是否是字母异位词的条件。具体看代码。

另外:对于两种方法的时间复杂度,由于代码中只有判断字母异位词的方法不同,第一种方式需要排序,时间复杂度为nlog(n),第二种方法只需要一次遍历,时间复杂度为n,所以第二种方法时间复杂度更低。但是第二种方式是计算若干个质数的乘积,当字符串很长的时候,乘积有可能超出int的范围,此时需要用long来表示,更长的时候,此方法就不可行了,只能通过第一种方法了。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

public class Solution_49 {
    /**
     * 时间复杂度:12ms,98.96%
     * 空间复杂度:41.6 MB,98.42%
     */
    public List<List<String>> groupAnagramsOne(String[] strs) {
        List<List<String>> res = new ArrayList<>();
        //字母异位词都有一个共同的本质,我们以他们共同的本质为key以一个存放他们的容器list为value构建hashMap
        HashMap<String, ArrayList<String>> hashMap = new HashMap<>();
        for (String str : strs) {
            char[] chars = str.toCharArray();
            //在本方法中,我们以排序后的字符串作为字母异位词的“本质”
            Arrays.sort(chars);
            String strAfterSort = new String(chars);
            if (hashMap.get(strAfterSort) == null) {
                ArrayList<String> list = new ArrayList<>();
                list.add(str);
                hashMap.put(strAfterSort, list);
                res.add(list);
            } else {
                hashMap.get(strAfterSort).add(str);
            }
        }
        return res;
    }

    /**
     * 时间复杂度:9ms,99.76%
     * 空间复杂度:41.8 MB,98.19%
     */
    public List<List<String>> groupAnagrams(String[] strs) {
        List<List<String>> res = new ArrayList<>();
        //字母异位词都有一个共同的本质,我们以他们共同的本质为key以一个存放他们的容器list为value构建hashMap
        HashMap<Integer, ArrayList<String>> hashMap = new HashMap<>();
        int[] prime = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 41, 43, 47,
                53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103};
        for (String str : strs) {
            char[] chars = str.toCharArray();
            //在本方法中,我们以字符串中每个字符的代表的质数的乘积作为字母异位词的“本质”
            int key = 1;
            for (char ch : chars) {
                key *= prime[ch - 'a'];
            }
            if (hashMap.get(key) == null) {
                ArrayList<String> list = new ArrayList<>();
                list.add(str);
                hashMap.put(key, list);
                res.add(list);
            } else {
                hashMap.get(key).add(str);
            }
        }
        return res;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值