什么是变位词

变位词指的是一个单词可以通过改变其他单词中字母的顺序来得到,也叫做兄弟单词,如army->mary。

判断两个字符串s1和s2是否为变位词

经典的字符串变位词检测问题是比较不同数量级函数算法的一个典型例子。如果一个字符串是 另一个字符串的重新排列组合,那么这两个字符串互为变位词。比如,”heart”与”earth”互为变位 词,”python”与”typhon”也互为变位词。为了简化问题,我们设定问题中的字符串长度相同,都是由 26 个小写字母组成。我们需要编写一个接受两个字符串,返回真假,代表是否是一对变位词的布尔 函数。

解法1:对两个字符串中的字母进行逐个比对

思路:检查第一个字符串中的所有字符是不是都在第二个字符串中出现。 如果能够把每一个字符都“检查标记”一遍,那么这两个字符串就互为变位词。检查标记一个字符 要用特定值 None 来代替,作为标记。然而,由于字符串不可变,首先要把第二个字符串转化成一个列表。第一个字符串中的每一个字符都可以在列表的字符中去检查,如果找到,就用 None 代替以示标记。

时间复杂度:O(n^{2})

def is_anagram(str1, str2):
str2_list = list(str2)
pos_1 = 0
still_ok = True
while pos_1 < len(str1) and still_ok:
pos_2 = 0
found = False
while pos_2 < len(str2_list) and not found:
if str1[pos_1] == str2_list[pos_2]:
found = True
else:
pos_2 = pos_2 + 1
if found:
str2_list[pos_2] = None
else:
still_ok = False
pos_1 = pos_1 + 1
return still_ok
print(is_anagram('apple', 'pepla'))

解法2:排序比对

思路:先将两个字符串转换成两个列表,然后对这两个列表进行排序,然后对两个列表中的元素进行一一比对,如果完全一致,说明是变位词,如果不是完全一致,说明不是变位词。

时间复杂度:O(n^{2})

def is_anagram(str1, str2):
str1_list = list(str1)
str2_list = list(str2)
str1_list.sort()
str2_list.sort()
pos = 0
match = True
while pos < len(str1) and match:
if str1_list[pos] == str2_list[pos]:
pos = pos + 1
else:
match = False
return match
print(is_anagram('apple', 'pepla'))

解法3:计数比较

思路:解决变位词问题的最后一个方法利用了任何变位词都有相同数量的 a,相同数量的 b,相同数量 的 c 等等。为判断两个字符串是否为变位词,我们首先计算每一个字符在字符串中出现的次数。由于

共有 26 个可能的字符,我们可以利用有 26 个计数器的列表,每个计数器对应一个字符。每当我们 看到一个字符,就在相对应的计数器上加一。最终,如果这两个计数器列表相同,则这两个字符串 是变位词。

时间复杂度:O(n)

def is_anagram(str1, str2):
count_str1 = [0] * 26
count_str2 = [0] * 26
for i in range(len(str1)):
pos = ord(str1[i]) - ord('a')
count_str1[pos] = count_str1[pos] + 1
for i in range(len(str2)):
pos = ord(str2[i]) - ord('a')
count_str2[pos] = count_str2[pos] + 1
j = 0
still_ok = True
while j < 26 and still_ok:
if count_str1[j] == count_str2[j]:
j = j + 1
else:
still_ok = False
return still_ok
print(is_anagram('apple', 'pepla'))