判断两个词是否为易位构词(anagram)

题目

易位同构词是指,一个词是另一个词的字母重排列,比如"heart"和"earth","python"和"typhon"均互为易位同构词。我们的目标是写一个判断函数,参数是两个字符串,函数返回它们是不是易位同构词。

解答思路一 :逐个检查

首先检查字符串的长度,然后查看第一个字符串中的每个字母是否出现在第二个字符串中。如果能遍历完,说明这两个字符串是易位同构词。另外,由于可能会出现重复字母的情况,所以对第二个字符串中检查过的字符都标记为None。

def anagramSolution1(s1,s2):
    if len(s1) != len(s2):  # 若长度不等,返回false
        stillOK = False

    alist = list(s2)  # 把s2表示成一个列表
 
    pos1 = 0
    stillOK = True

    while pos1 < len(s1) and stillOK:  # 遍历s1
        pos2 = 0
        found = False
        while pos2 < len(alist) and not found:  # 遍历s2中的元素
        	# 在s2中找到一个和s1[pos1]相等的元素时,found=True,循环结束
            if s1[pos1] == alist[pos2]:  
                found = True
            else:
                pos2 = pos2 + 1

        if found:  # 把s2中和s1[pos1]相等的元素置为None
            alist[pos2] = None
        else:
            stillOK = False

        pos1 = pos1 + 1

    return stillOK

print(anagramSolution1('abcd','dcba'))

时间复杂度 O(n^2)

s1中的每个字符,都会导致s2中最多n个字符的迭代,所以时间复杂度是
∑ i = 1 n i = n ( n + 1 ) 2 = 1 2 n 2 + 1 2 n \sum_{i=1}^n i=\frac{n(n+1)}{2}=\frac{1}{2}n^2+\frac{1}{2}n i=1ni=2n(n+1)=21n2+21n
也就是 O ( n 2 ) O(n^2) O(n2)

解答思路二 :排序并比较

虽然两个字符串不同,但包含的字母是相同的,所以可以先分别进行排序,然后再在每个位置上进行比较。

def anagramSolution2(s1,s2):
    alist1 = list(s1)
    alist2 = list(s2)

    alist1.sort()
    alist2.sort()

    pos = 0
    matches = True

    while pos < len(s1) and matches:
        if alist1[pos]==alist2[pos]:
            pos = pos + 1
        else:
            matches = False

    return matches

print(anagramSolution2('abcde','edcba'))

时间复杂度 O(n^2)或O(nlogn)

这种方法乍看之下似乎是 O ( n ) O(n) O(n)的时间复杂度,因为只经过了一次遍历。但是,在排序部分是有时间复杂度的,而排序才是决定算法整体时间复杂度的因素。所以,本算法的时间复杂度,也就是排序算法的时间复杂度一般为 O ( n 2 ) O(n^2) O(n2) O ( n l o g n ) O(nlogn) O(nlogn)

解答思路三 :暴力破解

因为s1和s2只是字母排列组合不同,所以可以对s1列举出所有重排列的方法,然后在这些方法中寻找是否有s2的存在。

时间复杂度 O(n!)

这里的时间复杂度是 O ( n ! ) O(n!) O(n!)

解答思路四 :利用字母出现的次数

在s1中出现的字母及其次数,和s2中出现的字母及其次数是一样的,所以可以先统计两个字符串中出现的字母及其次数,然后进行比较。

def anagramSolution4(s1,s2):
    c1 = [0]*26
    c2 = [0]*26

    for i in range(len(s1)):
        pos = ord(s1[i])-ord('a')
        c1[pos] = c1[pos] + 1

    for i in range(len(s2)):
        pos = ord(s2[i])-ord('a')
        c2[pos] = c2[pos] + 1
	
	'''这一段等同于下面的代码
	for k in range(26):
        if c1[k]!=c2[k]:
            stillOK=False
            break
    return stillOK
	'''

    j = 0
    stillOK = True
    while j<26 and stillOK:
        if c1[j]==c2[j]:
            j = j + 1
        else:
            stillOK = False

    return stillOK

print(anagramSolution4('apple','pleap'))

时间复杂度 O(n)

前面的两次迭代是基于 O ( n ) O(n) O(n)的时间复杂度,第三次迭代的时间是
T ( n ) = 2 n + 26 T(n)=2n+26 T(n)=2n+26,所以一共是 O ( n ) O(n) O(n)的时间复杂度。
但是这个算法需要额外的空间来保存两个字符串的计数列表,所以是牺牲空间来换时间。

参考:
AnAnagramDetectionExample

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值