Leetcode算法——49、字符串分组(group anagrams)

76 篇文章 1 订阅

给定一个字符串数组,将所有字符串分组,每一组的字符串包含的字符相同但是顺序不同。

示例:

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

思路

本文提出了 3 种解法,可以抽象出一个共同的思路:

都是定义了一种映射,将字符串映射到一个key,并保证同一组字符串映射到相同的key,不同组字符串映射到不同的key。

1、排序法

对每个字符串,先排序,然后作为 key,将原字符串加入到 key 对应的 value 中。

这样,不同字符顺序的字符串排序后 key 都相等,因此一个 key 对应的 value 自成一组。

示例:

‘aab’ -> ‘aab’
‘aba’ -> ‘aab’
key 相等,因此分到一组。

排序的算法复杂度为 O(nlogn),因此整体算法复杂度为 O(mnlogn)。

m为字符串个数,n为每个字符串的平均长度。

2、计数法

对每个字符串,对包含的字符的种类和个数进行统计,然后将同样记录结果的字符串聚集在一起。

可以用一个 26 位的字符串作为 key,代表 26 个字母的个数。

示例:

‘aab’ -> ‘21000000000000000000000000’
‘aba’ -> ‘21000000000000000000000000’
key 相等,因此分到一组。

相当于也是用了排序法,只不过是桶排序,算法复杂度为O(n),因此整体算法复杂度为O(mn)。

3、累乘法

将字符串中每个字符对应素数的累乘,将结果作为 key。

26 个字母对应的素数可以是任意的,只要互不相同即可,如:
[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]

示例:

‘aab’ -> 223=12
‘aba’ -> 232=12
key 相等,因此分到一组。

缺点:乘积结果与字符串长度成指数增长,容易数据溢出。

整体算法复杂度为O(mn)。

python实现

def groupAnagrams(strs):
    """
    :type strs: List[str]
    :rtype: List[List[str]]
    排序法。
    """
    dic = dict()
    for s in strs:
        key = str(sorted(s))
        dic[key] = dic.get(key, []) + [s]
    return list(dic.values())

def groupAnagrams2(strs):
    """
    :type strs: List[str]
    :rtype: List[List[str]]
    计数法。
    """
    dic = dict()
    for s in strs:
        l = [0] * 26 # 26个字母的计数
        for char in s:
            l[ord(char) - ord('a')] += 1
        key = str(l)
        dic[key] = dic.get(key, []) + [s]
    return list(dic.values())

from functools import reduce 
def groupAnagrams3(strs):
    """
    :type strs: List[str]
    :rtype: List[List[str]]
    累乘法。
    """
    prime_list = [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]
    dic = dict()
    for s in strs:
        if s:
            char_to_primes = [prime_list[ord(char) - ord('a')] for char in s]
            key = reduce(lambda x,y : x*y, char_to_primes)
        else:
            key = 0
        dic[key] = dic.get(key, []) + [s]
    return list(dic.values())

if '__main__' == __name__:
    strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
    print(groupAnagrams3(strs))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值