[Java·算法·中等]LeetCode49. 字母异位词分组

👉️ 力扣原文

题目

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

字母异位词 是由重新排列源单词的字母得到的一个新单词,所有源单词中的字母通常恰好只用一次。

字母异位词是指由相同的字母按照不同的顺序组成的单词,比如 “tea” 和 “eat” 就是字母异位词。在字母异位词分组问题中,需要把给定的一组字符串按照它们是否是字母异位词进行分组。
举个例子,如果我们有一个字符串数组 [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”],我们需要把其中所有的字母异位词分成一组。因为 “eat” 和 “ate”、“tea” 是字母异位词,所以它们应该被放到同一组;同理,“tan”、“nat” 也应该被放到一组;而 “bat” 是一个孤立的单词,应该自成一组。因此最终得到的分组结果是 [[“eat”,“ate”,“tea”],[“tan”,“nat”],[“bat”]]。

示例

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

分析思路1

排序:
创建一个 HashMap,用于存储每个字母异位词对应的单词列表。
遍历字符串数组中的每个单词,把它们转换成字符数组并排序,得到一个按字典序排列的相同字符串。
判断这个相同字符串是否已经存在于 HashMap 中,如果不存在,则创建一个新的键值对;否则在对应的值列表中添加该单词。
最后返回所有的值列表即可。

题解1


public class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        if (strs == null || strs.length == 0) return new ArrayList<>();
        
        Map<String, List<String>> map = new HashMap<>();
        for (String s : strs) {
            char[] ch = s.toCharArray();
            Arrays.sort(ch);
            String key = String.valueOf(ch);
            if (!map.containsKey(key)){
                map.put(key, new ArrayList<>());
            } 
            map.get(key).add(s);
        }
        return new ArrayList<>(map.values());
    }
}

执行结果
在这里插入图片描述

分析思路2

计数:
由于互为字母异位词的两个字符串包含的字母相同,因此两个字符串中的相同字母出现的次数一定是相同的,故可以将每个字母出现的次数使用字符串表示,作为哈希表的键。

由于字符串只包含小写字母,因此对于每个字符串,可以使用长度为 262626 的数组记录每个字母出现的次数。

题解2

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        Map<String, List<String>> map = new HashMap<String, List<String>>();
        for (String str : strs) {
            int[] counts = new int[26];
            int length = str.length();
            for (int i = 0; i < length; i++) {
                counts[str.charAt(i) - 'a']++;
            }
            // 将每个出现次数大于 0 的字母和出现次数按顺序拼接成字符串,作为哈希表的键
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < 26; i++) {
                if (counts[i] != 0) {
                    sb.append((char) ('a' + i));
                    sb.append(counts[i]);
                }
            }
            String key = sb.toString();
            List<String> list = map.getOrDefault(key, new ArrayList<String>());
            list.add(str);
            map.put(key, list);
        }
        return new ArrayList<List<String>>(map.values());
    }
}

执行结果
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值