题目:
写bool函数判断两个词是不是变位词
变位词: 字母完全相同(大小写也相同),但是顺序不同的词。
如 python , typhon. heart , earth, 为了简单起见,本题假设参与判断的两个词仅由小写
字母构成,而且长度相等,因为长度不等一定不是变位词
1. 解法1:逐个字母比较
遍历第一个词中的每个字母,
逐个在第二个词中找相同的字母,
找到时,将第二个词中此字母设置位None(即图中的对勾)避免重复,
当第二个词全是None时,他们时变位词,否则不是

写法一
def displacement_word(word1, word2):
word1_list = list(word1) # 把第一个单词存入列表中
word2_list = list(word2)
if len(word1_list) != len(word2_list): # 长度不同的词一定不是变位词
return False
for i in range(len(word1_list)): # word1 的每个字母, 逐个和 word2 中的每个字母比较
for j in range(len(word2_list)):
if word1_list[i] == word2_list[j]:
word2_list[j] = None # 如果两个字母相同,就把 word2 里面的变成 None,即打上勾,避免重复比较
for k in word2_list:
if k is not None: # 当 word2_list 中都是None时, 表示word1 一一对应了
return False
else:
return True
print(displacement_word("heart", "earth"))
写法二
def anagramSolution1(word1, word2):
result = True
list1 = list(word1) # 变成列表好做对比
list2 = list(word2)
if len(word1) != len(word2) or word1 == word2 : # 长度不同 或 两个词完全相同一定不是变位词
result = False
else:
for i in range(len(list1)):
for j in range(len(list2)):
if list1[i] == list2[j]: # 逐个word1的字母 和word2挨个比较
list2[j] = None # 相同时,将word2标记为None,避免重复比较
for i in range(len(list2)):
if list2[i] != None: # 是变位词的话 list2种的每个字母都是None
result = False
else:
result = True
return result
print(anagramSolution1('Python', 'tyPhon'))
问题规模是 n n n个字母,算法复杂度是双重循环那里 O ( n 2 ) O(n^2) O(n2)
2. 解法2 先排序再比较
两个词按照字母顺序排好序,
两个变位词排序后的是完全相同的

def anagramSolution2(word1, word2):
list1 = list(word1)
list2 = list(word2)
list1.sort() # 按字母顺序排序
list2.sort()
result = True
if len(word1) != len(word2) or word1 == word2 : # 长度不同 或 两个词完全相同一定不是变位词
result = False
else:
if list1 != list2: # 变位词再排序后的列表是完全相同的
result = False
return result
print(anagramSolution2('abcd', 'acdb'))
sort函数的算法杂度是 O ( n l o g n ) O(nlogn) O(nlogn)
3.解法3:暴力法
穷举所有用第一个单词的字母排列可能出现的所有的单词。
然后看第二个单词是不是其中的一个。
难度在于找到第一个单词所有字母的全排列,全排列的字符串个数是
n
!
n!
n!个。
注意:阶乘比指数更复杂,即
O
(
n
!
)
>
O
(
2
n
)
O(n!) > O(2^n)
O(n!)>O(2n)
因此暴力法不好。
4.解法4:计数法
对比两个词中每个字母出现的次数,如果26个字母出现的次数都相同的
话,这两个字符串就一定是变位词
计数完成后,进入比较阶段,看两个字符串的计数器是否相同,如果相同则输出是变位词的结论

def anagramSolution3(word1, word2):
c1 = [0] * 26
c2 = [0] * 26
result = True
for i in range(len(word1)):
pos = ord(word1[i]) - ord('a') # ord函数是ASCII
c1[pos] = c1[pos] + 1
for i in range(len(word2)):
pos = ord(word2[i]) - ord('a') # ord函数是ASCII
c2[pos] = c2[pos] + 1
if c1 != c2:
result = False
return result
print(anagramSolution3('apple', 'pleap'))
算法复杂度 O ( n ) O(n) O(n)
参考文献
本文的知识来源于B站视频 【慕课+课堂实录】数据结构与算法Python版-北京大学-陈斌-字幕校对-【完结!】,是对陈斌老师课程的复习总结