剑指Offer || 033.字母异位词分组

本文介绍了解决LeetCode第49题的算法,涉及将字符串数组中的变位词组合在一起,通过计数和哈希技巧,如构建int[]数组表示字符频率,然后使用字符串或long作为哈希值,将具有相同字符频率的字符串归类到一起。
摘要由CSDN通过智能技术生成

题目

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

注意:若两个字符串中每个字符出现的次数都相同,则称它们互为变位词。

示例 1:

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

示例 2:

输入: strs = [""]
输出: [[""]]

示例 3:

输入: strs = ["a"]
输出: [["a"]]

提示:

  • 1 <= strs.length <= 104
  • 0 <= strs[i].length <= 100
  • strs[i] 仅包含小写字母

注意:本题与主站 49 题相同: 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

LCR 033. 字母异位词分组 - 力扣(LeetCode)

题解

思路一:有问题,在迭代器(map)迭代的过程中不能删除元素,否则会报错。

代码:

public List<List<String>> groupAnagrams(String[] strs) {
    	Map<String,int[]> sums=new HashMap<String, int[]>();
    	for(String s:strs) {
    		int[] sum=new int[26];
    		for(int i=0;i<s.length();i++) {
    			sum[s.charAt(i)-'a']++;
    		}
    		sums.put(s,sum);
    	}
    	List<List<String>> result = new ArrayList<List<String>>();
    	for(String s : sums.keySet()) {
    		int[] tmp=sums.get(s);
    		List<String> result2 = new ArrayList<String>();
    		result2.add(s);
    		sums.remove(s);
    		//运行时会报错,循环过程中修改map不好改
    		for(String s2:sums.keySet()) {
    			int[] tmp2=sums.get(s2);
    			for(int i=0;i<26;i++) {
    				if(tmp[i]!=tmp2[i]) break;
    			}
    			result2.add(s2);
    			sums.remove(s2);
    		}
    	result.add(result2);
    	}
    	return result;
    }

思路二:使用排序(适用于String都不长时使用)

代码:

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        Map<String, List<String>> map = new HashMap<String, List<String>>();
        for (String str : strs) {
            char[] array = str.toCharArray();
            Arrays.sort(array);
            String key = new String(array);
            List<String> list = map.getOrDefault(key, new ArrayList<String>());
            list.add(str);
            map.put(key, list);
        }
        return new ArrayList<List<String>>(map.values());
    }
}

思路三:计数。

关键在于提取总结出sums<String,int[]>后如何进行

1.判断int[]相等。设计一个简单的hash函数代替遍历map的查询对比,将int[]转换成long或者拼接成str,例如key+=key*10+int[i]。这时可以map<String或者Long,List<String>>,使用hash值和列表对应。
2.能找到对应的String。不要想先将String转化成map再操作,在第一个迭代循环内就对应完成result的add

代码:

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
    	Map<String,List<String>> result = new HashMap<String, List<String>>();
    	for(String s:strs) {
    		int[] sum=new int[26];
    		for(int i=0;i<s.length();i++) 
    			sum[s.charAt(i)-'a']++;
    		StringBuffer sb = new StringBuffer();
    		for(int j=0;j<26;j++) {
    			//这个hash是有问题的,都是0101,有重复的可能。加入字母则不会
    			//sb.append(sum[j]);
    			if(sum[j]!=0) {
    				sb.append(j+'a');
    				sb.append(sum[j]);
    			}
    		}
    		String str=sb.toString();
    		List<String> sresult=result.getOrDefault(str, new ArrayList<String>());
    		sresult.add(s);
    		result.put(str, sresult);
    	}
    	return new ArrayList<List<String>>(result.values());
    }
}

sb.append(sum[j])的hash不对。["bdddddddddd","bbbbbbbbbbc"]

都是01010,因为append的时候10加进来是“10”而不是“01”,所以不是从右往左的。若从右往左加,可以考虑使用long型,key+=key*10+sum[j]。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值