testing if strings are anagrams有很多方法。但是,我想知道是否有一种方法可以仅对每个单词进行一次迭代吗?如果不是,那么用Python做到这一点的最有效方法是什么?
我们可以遍历第二个字符串,以检查第一个字符串中是否存在每个字符。但是,当使用内置 __contains__()
方法(称为__iter__()
方法)时,在最坏的情况下(反转图),我们可以在第一个字符串上进行n-1次迭代。
def is_anagram(str_1, str_2):
#chceck if same length
if (len(str_1) != len(str_2)):
return False
else:
#lowercase all characters
str1, str2 = list(str_1.lower()),list(str_2.lower())
for letter in str1:
if letter not in str2:
return False
str2.remove(letter)
return True
还有其他方法吗?
答案 0 :(得分:2)
如果您可以使用Collections.Counter,那么它将变得很简单,因为如果两个单词是字谜,它们将具有相同的键和相同的值。
from collections import Counter
def is_anagram(word1,word2):
return Counter(word1)==Counter(word2)
word1 = 'ahbgrettf'
word2 = 'arethbfgt'
print(is_anagram(word1,word2)
如果使用defaultdict,可以添加到@Maxime的答案中,我们不必检查键是否存在,然后检查键是否匹配以及值是否匹配,以确定其字谜。
from collections import defaultdict
def is_anagram(word1,word2):
table1, table2 = defaultdict(int), defaultdict(int)
for c in word1:
table1[c]+=1
for c in word2:
table2[c]+=1
if set(table1.keys()) == set(table2.keys()):
for k, v in table1.items():
if table2[k]!=v:
return False
else:
return False
return True
print(is_anagram('ahbgrettf','arethbfgt'))
答案 1 :(得分:1)
也许有字典?
编辑:添加了丹的建议
word1 = 'ahbgrettf'
word2 = 'arethbfgt'
def is_anagram(word1, word2):
if (len(word1) != len(word2)):
return False
word_dic = {}
# n iterations
for char in word1:
if word_dic.get(char):
word_dic[char] += 1
else:
word_dic[char] = 1
# n iterations
for char in word2:
if word_dic.get(char):
word_dic[char] -= 1
else:
return False
# n iterations
for v in word_dic.values():
if v != 0:
return False
return True
print(is_anagram(word1, word2))
总计:3n吗?
答案 2 :(得分:0)
您可以使用defaultdict来使用默认值,并创建一个字母频率字典,并用O(3n)的另一个字符串从中减去
from collections import defaultdict
def is_anagram2(str_1, str_2):
#check if same length
if (len(str_1) != len(str_2)):
return False
#creates a dictionary with default value of 0 for all keys
str_1_dict = defaultdict(int)
#adds how many of each letter in the dictionary
for i in str_1:
str_1_dict[i] += 1
#subracts how many of each letter in the dictionary
for i in str_2:
str_1_dict[i] -= 1
#checks to make sure all values are 0 (same number of each letter in both strings)
for i in str_1_dict:
if not str_1_dict[i] == 0:
return False
return True
is_anagram2('aaaa','aaaa')
答案 3 :(得分:0)
我认为使用字典确实是最快的,因为排序至少需要 O(nlogn)。另一方面,创建字典应该有效地采用 O(n + n) 或 O(n)。 .get() 确保键是否已经存在,返回默认值 0,然后添加 1 以插入键并将字典中的值初始化为 1。最后,将两个字典等同可确保两个字典中存在相同的键:值对。或者,您可以检查两个字符串的长度,如果长度不匹配,则在开头返回 false。
def anagram_checker(str1, str2):
str1 = str1.replace(" ", "").lower() #optional
str2 = str2.replace(" ", "").lower() #optional
str1_char_dict = {}
str2_char_dict = {}
for char in str1:
str1_char_dict[char] = str1_char_dict.get(char, 0) + 1
for char in str2:
str2_char_dict[char] = str2_char_dict.get(char, 0) + 1
return str1_char_dict == str2_char_dict