问题描述
我想知道一个字符串是否至少等于另一个字符串的排列之一。
例如,下面两个比较的输出必须是true
:
print('united states of America' == 'America united states of')
print('united states of America' == 'states of united America')
我使用了 itertools.permutations
方法来查找排列,但是
我想要的是单词而不是句子或字符串中的字母。
所以不是 'abcd' == 'bcad'
等于 True
,而是 'a b c d' == 'b c a d'
应该是 True
。
解决方法
您不需要itertools.permutations
。相反,比较重新排序的字符串,所有单词都已排序:
def reorder_str(s):
return " ".join(sorted(s.split()))
print(reorder_str('united states of America') == reorder_str('America united states of'))
# True
print(reorder_str('united states of America') == reorder_str('america united states of'))
# False
,
应该这样做:
import itertools
def f(s1,s2):
perms = itertools.permutations(s1.split(" "))
return tuple(s2.split(" ")) in perms
>>> f('united states of America','America united states of')
True
>>> f('united states of America','states of united America')
True
>>> f("a b c d","b a c d")
True
,
我推荐的解决方案是找到每个字符串中每个单词的频率并进行比较。
实际实现有点棘手,我们首先找到第一个字符串中每个单词的频率,然后对于第二个字符串中的每个单词我们将频率减1,如果频率小于0,我们知道第二个字符串比第一个字符串有更多次这个词,我们可以跳过其余的词。
def compare(s1,s2):
count = {} # this is the frequencies dict
for word in s1.split():
count[word] = count.get(word,0) + 1 # increment the frequency of the word
for word in s2.split():
count[word] = count.get(word,0) - 1 # decrement the frequency of the word
if count[word] < 0:
# s2 has more of this word than s1
return False
return True
此算法比排序或 itertools.permutations
更快,但占用更多空间。该算法的时间复杂度为 O(n)
,其中 n
是单词数,而 O(nlog n)
用于排序,O(n!)
用于 itertools.permutations
。
只需检查词频
from collections import Counter
c = Counter('united states of America')
c1 = Counter('America united states of')
c2 = Counter('states of united America'
print(c == c1 == c2)
# True
,
与排列相比,在计算上更有效的方法是拆分和排序字符串并比较排序的列表。生成排列的一个挑战是,一旦你开始只得到几个词,例如10,那么你就有10!生成的排列数 (3628800),您可以将其与字符串进行比较,使其非常低效且非常快。
string_1 = "states of united America"
string_2 = "united states of America"
def check_if_perm(s1,s2):
return sorted(s1.split()) == sorted(s2.split())
输出:
True
,
如果 itertools.permutations
不是必须的,我会使用集合:
>>> set('united states of America'.split()) == set('America united states of'.split())
True
>>> set('united states of America'.split()) == set('America united states off'.split())
False