本实战通过编写四个Python程序,分别采用逐个比较法、排序比较法、计数比较法和相互包含法来解决变位词检测问题。逐个比较法的时间复杂度为 O ( n 2 ) \text{O}(n^2) O(n2),虽然实现简单但效率较低;排序比较法则利用字符串排序后直接比较,时间复杂度为 O ( n l o g n ) \text{O}(n log n) O(nlogn),效率相对较高;计数比较法则统计字符出现次数进行对比,时间复杂度为 O ( n ) \text{O}(n) O(n),是四种方法中最高效的;而相互包含法则分别检查两个字符串中的字符是否完全包含对方,时间复杂度为 O ( n ? m ) \text{O}(n*m) O(n?m)。
在实际应用中,针对不同的场景需求和输入规模,可选择合适的算法以达到时间和空间效率的最佳平衡。例如,在处理大规模字符串时,计数比较法更优;而在较小规模或对内存有限制的场景下,排序比较法可能是更好的选择。同时,强力法由于其极高的时间复杂度( n ! n! n!),不适用于实际问题求解。
变位词侦测问题解法01-逐个比较法.py
'''
功能:变位词侦测问题解法01-逐个比较法
作者:华卫
日期:2024年01月13日
'''
def anagramSolution1(s1, s2):
stillOK = True
if len(s1) != len(s2):
stillOK = False
alist = list(s2)
pos1 = 0
while pos1 < len(s1) and stillOK:
pos2 = 0
found = False
while pos2 < len(alist) and not found:
if s1[pos1] == alist[pos2]:
found = True
else:
pos2 = pos2 + 1
if found:
alist.pop(pos2)
else:
stillOK = False
pos1 = pos1 + 1
return stillOK
str1 = input('Input the first string: ')
str2 = input('Input the second string: ')
if anagramSolution1(str1, str2):
print(str1, 'and', str2, 'are anagrams.')
else:
print(str1, 'and', str2, 'are not anagrams.')
anagramSolution1
的函数,用于检测两个输入字符串(s1和s2)是否为变位词。函数首先检查两个字符串的长度是否相等,如果不等,则直接返回False,表示它们不是变位词。
将第二个字符串s2
转换为字符列表alist
,便于进行元素操作。
使用变量pos1
遍历第一个字符串s1
的每个字符。
a. 初始化一个布尔变量found
为False,用于记录当前字符是否在alist
中找到。
b. 对于s1
中的每个字符,使用pos2
遍历alist
,寻找匹配项。
如果找到匹配项(即s1[pos1] == alist[pos2]
),将found
设为True,并跳出内层循环。
否则,将pos2
加1继续搜索下一个字符。
c. 如果找到了匹配项,从alist
中移除该字符(alist.pop(pos2)
);否则,将stillOK
设为False,表示无法构成变位词。
d. 将pos1
递增,准备处理下一个字符。
当遍历完s1
的所有字符且stillOK
仍为True时,说明s1
与s2
是变位词,函数返回True;否则返回False。
通过input()
获取用户输入的两个字符串str1和str2。
调用anagramSolution1(str1, str2)
函数判断这两个字符串是否为变位词。
根据函数返回的结果输出相应的信息,如果两个字符串是变位词,则输出"str1 and str2 are anagrams.“,否则输出"str1 and str2 are not anagrams.”。
此程序的时间复杂度为 O ( n 2 ) \text{O}(n^2) O(n2),其中n代表输入字符串s1和s2的长度(假设它们是等长的)。
首先检查两个字符串长度,时间复杂度为 O ( 1 ) \text{O}(1) O(1)。
将字符串s2转换为列表alist,时间复杂度为 O ( n ) \text{O}(n) O(n)。
使用两层循环进行逐个字符比较:
此外,在内层循环找到匹配项后执行的alist.pop(pos2)
操作,虽然在Python中平均时间复杂度为
O
(
n
)
\text{O}(n)
O(n),但在实际应用中(由于每次找到一个匹配项就移除一个元素),其对于整体时间复杂度的影响可以忽略不计,所以整体时间复杂度仍视为
O
(
n
2
)
\text{O}(n^2)
O(n2)。
T ( n ) = ∑ i = 1 n = n ( n + 1 ) 2 ≈ O ( n 2 ) \displaystyle \text{T}(n)=\sum_{i=1}^n=\frac{n(n+1)}{2}\approx \text{O}(n^2) T(n)=i=1∑n?=2n(n+1)?≈O(n2)
变位词侦测问题解法02-排序比较法.py
'''
功能:变位词侦测问题解法02-排序比较法
作者:华卫
日期:2024年01月13日
'''
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
str1 = input('Input the first string: ')
str2 = input('Input the second string: ')
if anagramSolution2(str1, str2):
print(str1, 'and', str2, 'are anagrams.')
else:
print(str1, 'and', str2, 'are not anagrams.')
anagramSolution2
的函数,用于检测两个输入字符串(s1和s2)是否为变位词。首先将输入的两个字符串s1
和s2
分别转换为字符列表alist1
和alist2
。
对这两个字符列表进行排序操作,排序后的列表中,相同的字符将会按照字典序排列到一起。
初始化一个变量pos
为0,表示当前比较的位置;同时初始化布尔值matches
为True,用以记录是否所有对应位置的字符都匹配成功。
使用while循环遍历两个已排序的字符列表,直到遍历完其中一个列表或发现不匹配为止:
alist1[pos] == alist2[pos]
),则将pos
加1继续比较下一个字符。matches
设置为False,跳出循环。循环结束后,根据matches
的值判断两个字符串是否为变位词:
matches
为True,则说明原字符串s1
和s2
是变位词,返回True。matches
为False,则说明它们不是变位词,返回False。通过input()
获取用户输入的两个字符串str1和str2。
调用anagramSolution2(str1, str2)
函数判断这两个字符串是否为变位词。
根据函数返回的结果输出相应的信息,如果两个字符串是变位词,则输出"str1 and str2 are anagrams.“,否则输出"str1 and str2 are not anagrams.”。
排序操作:对输入字符串s1
和s2
转换成的字符列表alist1
和alist2
进行排序。Python内置的sort()
方法采用Timsort
算法,其平均时间复杂度为
O
(
n
l
o
g
n
)
\text{O}(n log n)
O(nlogn),其中
n
n
n为列表长度(即字符串长度)。
遍历比较操作:在排序后的字符列表中,通过一个while循环逐个比较对应位置的字符是否相等,该过程的时间复杂度为 O ( n ) \text{O}(n) O(n)。
变位词侦测问题解法03-计数比较法.py
'''
功能:变位词侦测问题解法03-计数比较法
作者:华卫
日期:2024年01月13日
'''
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
j = 0
stillOK = True
while j < 26 and stillOK:
if c1[j] == c2[j]:
j = j + 1
else:
stillOK = False
return stillOK
str1 = input('Input the first string: ')
str2 = input('Input the second string: ')
if anagramSolution4(str1, str2):
print(str1, 'and', str2, 'are anagrams.')
else:
print(str1, 'and', str2, 'are not anagrams.')
anagramSolution4
的函数,用于检测两个输入字符串(s1和s2)是否为变位词。该方法采用计数比较法,统计每个字符串中各字符出现的次数,并进行比较。初始化两个长度为26的计数列表c1
和c2
,分别用于记录字符串s1
和s2
中小写字母的出现次数。这里假设输入字符串仅包含小写字母。
对于字符串s1
中的每一个字符:
ord(s1[i]) - ord('a')
得到(将字符转换为其ASCII值并减去’a’的ASCII值)。同样对字符串s2
执行相同的操作,更新计数列表c2
。
初始化一个变量j
为0,表示当前正在检查的小写字母的位置,以及一个布尔值stillOK
,初始值为True,表示目前所有已检查的字符计数都相等。
使用while循环遍历26个小写字母,如果在对应的索引位置上c1[j]
与c2[j]
相等,则继续检查下一个字母;否则,将stillOK
设置为False,跳出循环。
循环结束后,根据stillOK
的值判断两个字符串是否为变位词:
stillOK
仍为True,说明原字符串s1
和s2
是变位词,返回True。stillOK
变为False,则说明它们不是变位词,返回False。通过input()
获取用户输入的两个字符串str1和str2。
调用anagramSolution4(str1, str2)
函数判断这两个字符串是否为变位词。
根据函数返回的结果输出相应的信息,如果两个字符串是变位词,则输出"str1 and str2 are anagrams.“,否则输出"str1 and str2 are not anagrams.”。
此程序的时间复杂度为 O ( n ) \text{O}(n) O(n),其中 n n n表示输入字符串的长度。
在函数anagramSolution4
中,首先初始化了两个长度为26的列表c1
和c2
,时间复杂度为
O
(
1
)
\text{O}(1)
O(1)。
然后对s1
中的每个字符进行遍历,计算其在字母表中的位置并增加相应计数,循环次数为n(假设字符串仅包含小写字母),时间复杂度为
O
(
n
)
\text{O}(n)
O(n)。
同样地,对s2
中的每个字符执行相同的操作,时间复杂度也为
O
(
n
)
\text{O}(n)
O(n)。
最后,通过一个while循环比较两个计数列表是否相等,循环最多会进行26次(对于所有可能的小写字母),因此这一部分的时间复杂度是 O ( 1 ) \text{O}(1) O(1)级别的。
综合上述步骤,整个程序的主要时间消耗在于遍历字符串并统计字符出现次数的部分,故总时间复杂度为 O ( n ) \text{O}(n) O(n)。同时,由于空间上只使用了固定大小的计数数组,所以空间复杂度为 O ( 1 ) \text{O}(1) O(1)。
变位词侦测问题解法04-相互包含法.py
"""
功能:变位词侦测问题解法04-相互包含法
作者:华卫
日期:2024年01月13日
"""
def anagramSolution5(s1, s2):
stillOK = True
for i in range(len(s1)):
if s1[i] not in s2:
stillOK = False
break
if stillOK:
for i in range(len(s2)):
if s2[i] not in s1:
stillOK = False
break
return stillOK
str1 = input('Input the first string: ')
str2 = input('Input the second string: ')
if anagramSolution5(str1, str2):
print(str1, 'and', str2, 'are anagrams.')
else:
print(str1, 'and', str2, 'are not anagrams.')
anagramSolution5
的函数,用于检测两个输入字符串(s1和s2)是否为变位词。该方法采用了相互包含法,即检查一个字符串中的每个字符是否都出现在另一个字符串中。初始化一个布尔变量stillOK
为True,表示在没有发现不匹配字符的情况下,两个字符串可能是变位词。
使用一个for循环遍历字符串s1
中的每个字符:
s2
中,则将stillOK
设为False,并使用break语句跳出循环。这意味着s1
中存在s2
中没有的字符,因此它们不是变位词。当遍历完s1
后,如果stillOK
仍为True,则继续对字符串s2
进行相同的操作:
s2
中的每个字符。s1
中,则将stillOK
设为False,并同样使用break语句跳出循环。这意味着s2
中也存在s1
中没有的字符,因此它们不是变位词。在完成所有检查后,返回stillOK
的值。若为True,说明两个字符串是变位词;否则,它们不是变位词。
通过input()
获取用户输入的两个字符串str1和str2。
调用anagramSolution5(str1, str2)
函数判断这两个字符串是否为变位词。
根据函数返回的结果输出相应的信息,如果两个字符串是变位词,则输出"str1 and str2 are anagrams.“,否则输出"str1 and str2 are not anagrams.”。
此程序的时间复杂度为 O ( n ? m ) \text{O}(n*m) O(n?m),其中 n n n和 m m m分别为输入字符串s1和s2的长度。
在函数anagramSolution5
中,首先遍历字符串s1
,对每个字符执行一次查找操作(即s1[i] not in s2
),这需要在字符串s2
中进行线性搜索。最坏情况下,对于每个字符都需要遍历整个s2
,因此这部分时间复杂度为
O
(
m
)
\text{O}(m)
O(m)。
如果s1
中的所有字符都在s2
中找到,则继续遍历字符串s2
,再次对每个字符执行查找操作(即s2[i] not in s1
)。同样地,这部分在最坏情况下也具有
O
(
n
)
\text{O}(n)
O(n)的时间复杂度。
因此,总时间复杂度为这两部分之和,即 O ( n + m ) \text{O}(n+m) O(n+m),由于两者均与输入字符串的长度相关且相互独立,我们可以将其简化为 O ( n ? m ) \text{O}(n*m) O(n?m),表示随着两个字符串长度同时增加时,程序运行时间的增长趋势。
?