检查需要删除多少个字符才能在 Python 中生成字谜

Posted

技术标签:

【中文标题】检查需要删除多少个字符才能在 Python 中生成字谜【英文标题】:Check how many character need to be deleted to make an anagram in Python 【发布时间】:2021-09-03 16:54:33 【问题描述】:

我编写了 python 代码来检查需要从两个字符串中删除多少个字符才能使它们成为彼此的字谜。

这是问题陈述“给定两个字符串,and ,长度可能相同,也可能不同,确定生成和变位词所需的最小字符删除数。可以从任一字符串中删除任何字符”

def makeAnagram(a, b):
    # Write your code here
    ac=0 # tocount the no of occurences of chracter in a
    bc=0    # tocount the no of occurences of chracter in b
    p=False     #used to store result of whether an element is in that string
    c=0        #count of characters to be deleted to make these two strings anagrams
    t=[]        # list of previously checked chracters
    
    for x in a:
        if x in t == True:
            continue
        ac=a.count(x)
        t.insert(0,x)
        for y in b:
            p = x in b
            if p==True:
                bc=b.count(x)
                if bc!=ac:
                    d=ac-bc
                    c=c+abs(d)

            elif p==False:
                c=c+1 
                               
    return(c)

【问题讨论】:

【参考方案1】:

您可以为此使用collections.Counter

from collections import Counter

def makeAnagram(a, b):
    return sum((Counter(a) - Counter(b) | Counter(b) - Counter(a)).values())

Counter(x)(其中 x 是一个字符串)返回一个字典,将字符映射到它们在字符串中出现的次数。

Counter(a) - Counter(b) 为您提供了一个字典,它将b 中过多的字符映射到它们在b 中出现的次数超过它们在a 中出现的次数。

Counter(b) - Counter(a) 和上面一样,但是对于a 中过多的字符。

| 合并两个结果计数器。然后我们取这个值,并将它们相加以获得在任一字符串中过度表示的字符总数。这相当于形成一个字谜需要删除的最少字符数。


至于为什么您的代码不起作用,我无法确定任何一个问题。为了获得下面的代码,我所做的只是一些简化(例如删除不必要的变量,一起循环 a 和 b,删除 == True== False,将 t 替换为 set,为变量提供描述性名称等.),代码开始工作。这是简化的工作代码:

def makeAnagram(a, b):
    c = 0 # count of characters to be deleted to make these two strings anagrams
    seen = set() # set of previously checked characters
    for character in a + b:
        if character not in seen:
            seen.add(character)
            c += abs(a.count(character) - b.count(character))
    return c

我建议您重点学习如何编写简单/简短的代码。与实际处理算法并获得结果相比,这似乎并不重要。它可能看起来像是清理或造型工作。但它带来了巨大的回报。 Bug 在简单的代码中更难引入,也更容易被发现。通常,简单代码也会比等效的复杂代码更高效,这要么是因为程序员能够更容易地看到改进它的方法,要么是因为更简洁的代码自然而然地产生了更高性能的方法。

【讨论】:

感谢您的回答!你能解释一下我在那里做错了什么吗? @user9262680 我已经用你的代码的简化版本更新了答案。请将其与您的代码进行比较以尝试了解差异。看看您是否可以通过逐步简化代码的过程来获得简化的代码,只需进行少量更改 - 这将是一个很好的做法。希望这会有所帮助。【参考方案2】:

假设只有小写字母

这个想法是为字符串和每个字符的存储频率创建字符计数数组。现在迭代两个字符串的计数数组,两个字符串中任何字符abs(count1[str1[i]-‘a’] – count2[str2[i]-‘a’]) 的频率差异是任一字符串中要删除的字符数。

CHARS = 26
 
# function to calculate minimum
# numbers of characters
# to be removed to make two
# strings anagram
def remAnagram(str1, str2):
 
    
    count1 = [0]*CHARS
    count2 = [0]*CHARS
 
    i = 0
    while i < len(str1):
        count1[ord(str1[i])-ord('a')] += 1
        i += 1
 
    i =0
    while i < len(str2):
        count2[ord(str2[i])-ord('a')] += 1
        i += 1
 
    # traverse count arrays to find
    # number of characters
    # to be removed
    result = 0
    for i in range(26):
        result += abs(count1[i] - count2[i])
    return result
 

这里的时间复杂度是 O(n + m) 其中 n 和 m 是两个字符串的长度 空间复杂度为 O(1),因为我们只使用大小为 26 的数组

这可以通过仅使用单个数组进行计数来进一步优化。

在这种情况下,对于字符串 s1 -> 我们增加计数器 对于字符串 s2 -> 我们减少计数器

def makeAnagram(a, b):
    buffer = [0] * 26
    for char in a:
        buffer[ord(char) - ord('a')] += 1
    for char in b:
        buffer[ord(char) - ord('a')] -= 1
    return sum(map(abs, buffer))
if __name__ == "__main__" :
 
    str1 = "bcadeh"
    str2 = "hea"
    print(makeAnagram(str1, str2))

输出:3

【讨论】:

以上是关于检查需要删除多少个字符才能在 Python 中生成字谜的主要内容,如果未能解决你的问题,请参考以下文章

使用 SSH 命令在 python 中生成字典

如何通过Python删除Windows中的(g)zip文件? (在LabVIEW中生成的文件。)

在 Access 中生成随机字母数字字符串后检查重复项

在 Python 中生成非重复随机数

Unicode 范围以及python中生成所有Unicode的方法

为啥我需要单击两次才能在输入字段中生成一个值