LeetCode 49 字母异位词分组 | 解题思路分享

原题链接:49. 字母异位词分组 - 力扣(LeetCode)

题目难度:中等

题目描述

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

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

示例 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] 仅包含小写字母

我的解题思路

这题题目有点绕,我用大白话翻译一下,就是要把组成字母相同的字符串放在同一个列表里就行了

很显然是需要使用哈希来解题的,我们只需要将组成字母相同的字符串使用同一个kay存入到HashMap当中就可以了。只不过哈希的值只能和字符串内的字母组成相关,且不能与组成的顺序相关。

下面针对这题提供两种哈希的方法。

加与乘

首先我们把每个字符串中每个字母都当成一个数字来看。

根据我们中学(或者小学)学习的加法交换律和乘法交换律,可以知道多个数字之间相加相乘的结果是与其顺序无关的,故我们可以让字符串中的每个字母的值相乘或相加。

由于单独使用乘法或加法会出现不符合预期的情况,比如:2 * 3 = 1 * 6 = 61 + 5 = 3 + 3 = 6,这种情况下我们不希望得出相同的哈希值。

故我选择同时使用加法和乘法,可以极大的减小碰撞的概率。

核心代码如下:

long hash(String str) {
    if (str.equals("")) return -1;
    long ans = 1;
    // 先全部相乘
    for (int i = 0; i < str.length(); i++) {
        ans *= str.charAt(i);
    }
    // 再全部相加
    for (int i = 0; i < str.length(); i++) {
        ans += str.charAt(i);
    }
    return ans;
}

字母排序

当我们将字符串中的字母进行统一排序后,得到的值同样会与其组成顺序无关,且比加法乘法更加可靠。

只需要先将字符串转换成字符数组,对其进行排序后再转换成字符串,并作为key即可。

核心代码如下:

String hash(String str) {
    char[] array = str.toCharArray();
    Arrays.sort(array);
	return new String(array);
}

完整解题代码 Java

上面的哈希算法可以二选一,都能过题。

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {    
		HashMap<Long, List<String>> map = new HashMap<>();
		for (String str : strs) {
			long key = hash(str);
			List<String> list = map.getOrDefault(key, new ArrayList<>());
			list.add(str);
			map.put(key, list);
		}
		return new ArrayList<>(map.values());
	}

	long hash(String str) {
        if (str.equals("")) return -1;
		long ans = 1;
		for (int i = 0; i < str.length(); i++) {
			ans *= str.charAt(i);
		}
		for (int i = 0; i < str.length(); i++) {
			ans += str.charAt(i);
		}
		return ans;
	}
}

通过截图:

image-20230108160845773

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

阿杆.

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

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

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

打赏作者

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

抵扣说明:

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

余额充值