Python——“变位词”判断问题的四种解法

【题目描述】

所谓“变位词”是指两个词之间存在组成字母的重新排列关系

如:heart和earth,python和typhon

为了简单起见,假设参与判断的两个词仅由小写字母构成,而且长度相同

【解法1】

逐字检查法

【解法思路】

将词1中的字符逐个到词2中检查是否存在,如果存在就“打勾”标记(防止重复检查)

如果每个字符都能找到,则两个词就是变位词

只要有一个字符找不到,就不是变位词

【运算代码】

def anagramSolution(s1,s2):
    if len(s1)!=len(s2): #长度不同,直接结束
        return False
    list_1=list(s1) #将s1存入列表中
    n=len(s1) 
    for c in s2: #枚举第一个单词的每一个字母
        found = False #先定义False,假设找不到
        for i in range(n): #在列表s1中查找c
            if list_1[i]==c:
                return True 
                list_1[i]=None #做记号,找到就打勾
                break
        if not found: 
            return False
    return True
print(anagramSolution('ypthon','python')) #True

【算法分析】

外层循环遍历s2中的每一个字符,将内层循环执行n次,而内层循环在s1中查找字符,每一个字符的对比度数分别是1、2、3、...、n中的一个,而且各不相同。

所以总的执行次数是1+2+3+4+...+n ==>(1+n)*n/2 和公式

可知该解法的数量级为O(n^2)

【解法2】

排序比较

【解题思路】

将两个字符串都按照字母顺序排好序

再逐个字符对比是否相同,如果相同则是变位词

有任何不同就不是变位词

【运算代码】

def anagramSolution(s1,s2):
    #将单词转化为列表并排序
    list_1=list(s1) 
    list_2=list(s2)
    list_1.sort()
    list_2.sort()
    i=0 #计数
    found=True #返回结果
    while i<len(s1) and found:
        #逐个对比
        if list_1[i] ==list_2[i]:
            i+=1
        else:
            found=False
    return found
print(anagramSolution('ypthon','python')) #True

【算法分析】

粗看上去,本算法只有一个循环,最多执行n次,数量级是O(n)

但循环前面但两个sort并不是无代价的,会发现排序算法采用不同的解决方案,其运算时间数量级差不多是O(n^2)或者O(n log n),大过循环的O(n)

所以本算法时间主导的步骤是排序步骤

本算法的运算时间数量级就等于排序过程的数量级O(n log n)

【解法3】—— 暴力法

【解法思路】

暴力法解题思路为:穷尽所有可能组合

将s1中出现的字符进行全排列,再查看s2是否出现在全排列列表中。

这里最大困难是产生s1所有字符的全排列。

根据组合数学的结论,如果n个字符进行全排列,其所有可能的字符串个数为n!

【运算代码】

太过暴力,所以没有代码

【解法四】——计数比较

【解题思路】

对比两个词中每个字母出现的次数,如果26个字母出现的次数都相同的话,这两个字符串就一定是变位词

具体做法:为每一个词设置一个26位的计数器,先检查每一个词,在计数器中设定好每一个字母出现的次数

计数完成后:进入比较阶段,看两个字符串的计数器是否相同,如果相同则输出是变位词的结论

【运算代码】

def anagramSolution(s1,s2):
    a1=[0]*26
    a2=[0]*26
    for i in range(len(s1)):
        #ord()将字母转为Acsill码,得下标
        xb=ord(s1[i])-ord('a') 
        a1[xb]+=1
    for j in range(len(s2)):
        #ord()将字母转为Acsill码,得下标
        xb=ord(s1[j])-ord('a') 
        a2[xb]+=1
    j=0
    found=True
    while j<26 and found:
        if a1[j]==a2[j]:
            j+=1
        else:
            found=False
    return found

【算法分析】

计数比较算法中有3个循环迭代,但不像解法1那样存在嵌套循环

前两个循环用于对字符串进行计数,操作次数等于字符串长度n

第3个循环用于计数器比较,操作次数总是26次

所以总操作次数T(n)=2n+26,其数量级为O(n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值