解法三:计数比较
解题思路:对比两个词中每个字母出现的次数,如果26个字母出现都相同的话,这两个字符就一定是变位词
做法:为每个词设置一个26位的计数器,先检查每个词,在计数器中设定好每个字母出现的次数,完成之后,进行比较,看两个字符串的计数器是否相同,如果相同,则输出是变位词。
代码实现:
def anagramSolution(s1, s2):
# 初始化两个计数器[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
c1 = [0] * 26
c2 = [0] * 26
# 对s1进行计数,遍历次数要和字母的个数一致
for i in range(len(s1)):
# 引入ord函数 把字母在列表的索引计算出来
pos = ord(s1[i]) - ord('a')
# 计数器里面都加1,就变成了在字母表中的位置
c1[pos] = c1[pos] + 1
for i in range(len(s2)):
pos = ord(s2[i]) - ord('a')
c2[pos] = c2[pos] + 1
j = 0
stillOK = True
# 循环遍历
while j < 26 and stillOK:
# 如果两个计数器可以一一对象,则是变位词
if c1[j] == c2[j]:
j = j + 1
else:
stillOK = False
return stillOK
print(anagramSolution('apple', 'pleap'))
算法分析:
前两个循环用于对字符串进行计数,操作次数等于字符串的长度n,第三个循环用于计数器比较,操作次数总为26次,所以操作总次数为T(N)=2n+26,其数量级为O(n)
这是一个线性数量级的算法,是以上几个算法最优的,但是这个依赖于两个长度为26的计数器列表,来保存字符计数,这比前两个需要更多的存储空间
这个就是牺牲空间来换取时间的小案例
解法四:被称为暴力法或来枚法
将s1进行全排列,在判断s2是否在这个全排列的列表中
暴力法思路:穷尽所有可能的组合,12345这5个数字,可以组成多上个四位整数
可能的字符串个数就是n! 就是n的阶乘,这样情况是相当多的
所以,,,放弃此算法