LeetCode groupAnagrams Python3

本文介绍了一种有效的算法来解决字母异位词分组问题。通过使用Python中的字典和元组特性,该算法能高效地将一组字符串按字母异位词进行分类。

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

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

示例:
输入: [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”]
输出:
[
[“ate”,“eat”,“tea”],
[“nat”,“tan”],
[“bat”]
]

这道题让我知道了,原来在 Python 中 tuple 是 hashable 的,也就是说可以拿一个 tuple 作为字典的 key,但是 list 是不可以的

def groupAnagrams(strs):
	dic = {}
	for word in strs:
		count = [0] * 26
		for l in word:
			pos = ord(l) - ord('a')
			count[pos] += 1
		count = tuple(count)
		if dic.get(count):
			dic[count].append(word)
		else:
			dic[count] = [word]
	return list(dic.values())
### 问题解析 LeetCode 第49题 **Group Anagrams** 要求将字符串数组中的字母异位词(即由相同字符以不同顺序组成的字符串)归为一组。例如,输入 `["eat", "tea", "tan", "ate", "nat", "bat"]`,输出应为: ```python [ ["eat", "tea", "ate"], ["tan", "nat"], ["bat"] ] ``` 解决该问题的核心思路是找到一个统一的“特征”来标识每个异位词组。通常有两种方法实现这一点。 --- ### 方法一:排序作为键值 对于每个字符串,将其字符排序后得到的字符串可以作为字典的键。所有互为异位词的字符串在排序后会生成相同的键[^1]。 #### Python 实现 ```python from typing import List class Solution: def groupAnagrams(self, strs: List[str]) -> List[List[str]]: counts = dict() for s in strs: key = ''.join(sorted(s)) if key in counts: counts[key].append(s) else: counts[key] = [s] return list(counts.values()) ``` - 时间复杂度:O(n * k log k),其中 n 是字符串数量,k 是单个字符串的平均长度。 - 空间复杂度:O(n * k) --- ### 方法二:字符计数作为键值 另一种方式是以字符频率元组作为字典的键。例如,字符串 `"aab"` 的频率元组是 `(2, 1, 0, ..., 0)`,表示每个字母出现的次数。由于列表不能作为字典的键,因此使用元组形式存储[^2]。 #### Python 实现 ```python from collections import defaultdict from typing import List class Solution: def groupAnagrams(self, strs: List[str]) -> List[List[str]]: dic = defaultdict(list) for w in strs: count = [0] * 26 for c in w: count[ord(c) - ord('a')] += 1 dic[tuple(count)].append(w) return list(dic.values()) ``` - 时间复杂度:O(n * k),其中 k 是字符串长度。 - 空间复杂度:O(n * k) --- ### 方法三:逐行分析与手动构建结果 以下代码通过显式构建字典和结果列表完成分类。其逻辑清晰,适合初学者理解流程[^3]。 ```python from typing import List class Solution: def groupAnagrams(self, strs: List[str]) -> List[List[str]]: res = [] mdict = {} for word in strs: sorted_word = ''.join(sorted(word)) if sorted_word in mdict: mdict[sorted_word].append(word) else: mdict[sorted_word] = [word] for value in mdict.values(): res.append(value) return res ``` --- ### 方法四:使用索引映射 该方法先建立排序后的字符串到原始索引之间的映射,然后根据映射关系组织最终结果[^4]。 ```python from typing import List class Solution: def groupAnagrams(self, strs: List[str]) -> List[List[str]]: dict1 = {} for i, s in enumerate(strs): key = ''.join(sorted(s)) if key not in dict1: dict1[key] = [i] else: dict1[key].append(i) res = [] for indices in dict1.values(): group = [strs[i] for i in indices] res.append(group) return res ``` --- ### 方法五:异常处理机制实现 此解法尝试通过异常捕获机制动态更新结果数组,适用于不希望预先初始化字典的情况[^5]。 ```python from typing import List class Solution: def groupAnagrams(self, strs: List[str]) -> List[List[str]]: result = [] sMap = {} index = 0 flag = 0 for originS in strs: s = list(originS) s.sort() key = ''.join(s) try: sLocate = sMap[key] flag = 1 except KeyError: sMap[key] = index index += 1 tempList = [originS] result.append(tempList) flag = 0 if flag == 1: result[sLocate].append(originS) return result ``` --- ### 总结 上述几种方法均能正确解决 LeetCode 第49题,差异主要体现在数据结构的使用、代码风格以及性能优化上。推荐优先使用第一种或第二种方法,因其简洁高效,适合大多数实际场景。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值