剑指offer33:变位词组

题目:
给定一组单词,请将它们按照变位词分组。例如:输入一组单词[“eat”,“tea”,“tan”,“nat”,“bat”,“ate”],这组单词分为3组,分别是[“tea”,“ate”,“eat”],[“tan”,“nat”]和[“bat”]。
分析:
第一种思路是把每个英文小写字母映射到一个质数,例如a映射数字2,b映射数字3等等一直到z映射101(第26个质数)。单词“eat”可以映射到数字1562(11x2x71),如果同为变位词那么它们都会映射到相同数字,因此可以定义一个哈希表,哈希表的键是单词中字母映射的数字的乘积,而值为一组变位词。但是会出现一个潜在问题,由于把单词映射到数字用到了乘法,因此当单词非常长时可能会溢出
第二种思路就是一组变位词映射到同一个单词,互为变位词的单词的字母出现的次数相同,把单词中的字母按字母表的顺序排序就会得到同一个字符串,因此可以定义一个哈希表,哈希表的键是按照字母顺序排列的字符串,值是一组变位词。
代码:

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

public class GroupAnagrams {
//如果输入n个单词,平均每个单词由m个字母,那么第一种思路的时间复杂度是O(mn)
    public static List<List<String>> groupAnagrams1(String[] strs) {
        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 = 1;
            for (int i = 0; i < str.length(); i++) {
                wordHash *= hash[str.charAt(i) - 'a'];
            }
            //put与putIfAbsent区别:
//put在放入数据时,如果放入数据的key已经存在与Map中,最后放入的数据会覆盖之前存在的数据,
//而putIfAbsent在放入数据时,如果存在重复的key,那么putIfAbsent不会放入值。
            groups.putIfAbsent(wordHash, new LinkedList<String>());
            groups.get(wordHash).add(str);
        }
        return new LinkedList<>(groups.values());
    }
    public static List<List<String>> groupAnagrams2(String[] strs){
    //每个单词平均由m个单词,排序一个单词需要O(mlogm),如果每个单词由n个,该算法时间复杂度是O(nmlogn)
        HashMap<String, List<String>> groups = new HashMap<>();
        for (String str : strs) {
            char[] charArray = str.toCharArray();
            Arrays.sort(charArray);
            String s = new String(charArray);
            groups.putIfAbsent(s,new LinkedList<String>());
            groups.get(s).add(str);
        }
        return new LinkedList<>(groups.values());
    }

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龙崎流河

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值