【问题标题】:How can I fix my python word descrambler?如何修复我的 python 字解扰器?
【发布时间】:2021-04-20 03:40:24
【问题描述】:

问题:完成函数 scramble(str1, str2),如果 str1 字符的一部分可以重新排列以匹配 str2,则返回 true,否则返回 false。

注意事项:

仅使用小写字母 (a-z)。不包含标点符号或数字。 性能需要考虑

MY CODE:
s1 = 'rkqodlw'
s2 = 'world'

def scramble(s1, s2):
    unscrambled_word = []
    n = 0
    x = 0
    s1_list = list(s1)
    s2_list = list(s2)
    s1_letter = s1_list[n]
    s2_letter = s2_list[x]
    for letters in range(len(s2_list)):
        while n > len(s1_list):
            if s1_letter == s2_letter:
                n = n + 1
                x = x + 1
            else:
                n = n + 1
    return 'True' if x == len(s2_list) else 'False'

我正在尝试让我的代码剖析这两个字符串中的每一个。如果第一个字符串的单词与第二个字符串的单词不匹配,则 n 将 +1 并移动到第二个字母。如果匹配,则 n 和 x 都将 + 1。我对代码的想法是,如果 x == 在巨型循环结束之前第二个字符串的长度,那么它将返回 True。否则为假。问题在于循环。循环似乎只遍历两个字符串的前两个字母,然后停止。我是一个相当新的编码器,任何输入都非常感谢!谢谢!

【问题讨论】:

  • 您的预期回报是多少?如果 s1 是 s2 的加扰版本,您是否尝试返回 True,可能带有额外的字母?如果是这样,集合似乎是一个优雅的解决方案。
  • 我也想到了套装但是套装不起作用。如果第一个字是moon,第二个字是money,则结果为True,错误。当您尝试查看 word1 是否在 word2 中时
  • 您的总体想法似乎是正确的。不过,您的 while 循环有问题,您正在检查 n 是否大于列表的长度,并且由于 n 从 0 开始,因此您的 while 循环将永远不会执行。
  • 您需要对这两个词进行排序。然后按位置比较。如果不匹配则失败
  • 我什至不确定现在是什么系列,就像我说的我还是个新手。但我的想法是,只要我可以让程序验证第一个字符串中是否有足够的单词与第二个字符串中的单词匹配以创建第二个字符串单词,我就不需要解读这些单词。希望这会有所帮助。

标签: python


【解决方案1】:

您只需要确保 str2 中的字母在 str1 中都有足够的数量

def scramble(str1,str2):
    d1 = {}
    for c in str1:
        if not c in d1:
           d1[c] = 0
        d1[c] += 1
    for c in str2:
        if not c in d1 or d1[c] < 1:
            return False
        d1[c] -= 1
    return True

想法是遍历 str2 中的所有字符,例如,如果 str2 有三个“a”字母,请确保 str1 至少有三个“a”字母。这需要计算每个字符在 str1 中出现的次数。这很自然地用字典完成。字典将事物(称为键)映射到其他事物(称为值)。在这种情况下,我们将单个字符的键映射到数字计数的值。

第一步是创建一个空字典d1={}。 接下来是在 str1 中逐个字符地进行,这是第一个 for 循环。对于这些字符中的每一个,我们询问该字符之前是否曾被放入 d1。如果没有,那么我们在 d1 内为该字符创建一个新映射到起始值零。每次在此循环中通过 str1 遇到一个字符时,从 d1 中该字符映射的计数值增加 1。在第一个 for 循环(通过 str1)完成后,字典包含 str1 中每个字母的计数。

下一个想法是遍历 str2 中的每个字符。如果它是 d1 中不存在的字符,则意味着该字符不存在于 str1 中,因此 str1 缺少一个需要加扰到 str2 中的字符。此时,您可以停止处理并返回 False。

否则,如果您只遇到在 d1 中作为键存在的字符,则在 for 循环遍历 str2 时,每次遇到该字符时,您都会从 d1 映射的计数值中减去一个。如果减法会导致 d1 计数值低于零,那么这意味着 str2 具有比 str1 更多的特定字符数,因此 str1 不能再一次进入 str2。因此,您可以在此时返回 False 并停止处理。

最后,如果我们通过整个第二个循环(通过 str2)而没有遇到上述任何一种返回 False 的情况,这意味着 str1 至少具有与 str2 一样多的每个字符,因此可以争用 str2使用它的一些字母。然后返回 True。

【讨论】:

  • 我对计算机在您的某些代码中执行的操作有点困惑。你介意再分解一下并解释你的代码在做什么吗?对不起,我是大新手哈哈。
  • @Jace 我会添加更多解释
  • 点赞了解详情。性能方面,我看不出有什么能打败你的答案
  • @BingWang 实际上我很喜欢你对收藏的使用。你的很优雅。
【解决方案2】:
from collections import defaultdict
s1 = 'rkqodlw'
s2 = 'world'

def scramble(s, t):
    d=defaultdict(int)
    for c in s:
        d[c]+=1
    for c in t:
        d[c]-=1
    return min(d.values())>=0
scramble(s1,s2)

或者使用计数器

from collections import Counter
s1 = 'rkqodlw'
s2 = 'world'

def scramble(s, t):
    c=Counter(s)
    c.subtract(Counter(t))
    return min(c.values())>=0
scramble(s1,s2)

【讨论】:

    【解决方案3】:

    替代方案:

    s1 = 'rkqodlw'
    s2 = 'world'
    
    def scramble(s1, s2):
      s1_list = list(s1)
      for char in s2:
        if char in s1_list:
          s1_list.pop(s1_list.index(char))
        else:
          return False
      return True
    
    print(scramble(s1,s2))
    

    它的工作原理如下:您为 s2 中的每个字母运行循环,如果该字母也在 s1 的列表版本中,则从该列表版本中删除它。这样,例如,如果 s2 是 'rabbit',而 s1 是 'braintrain',您将遇到第一个 'r''a' 和第一个 'b',从 'braintrain' 中删除它以获得 'intrain' ,然后下一个 'b' 将无法通过测试并返回 False。如果有足够的'b's,扰频器将返回True。如果函数完成时测试从未失败(即 s2 中的所有字母也在 s1 中),则返回最终的 True

    【讨论】:

    • 你可以使用 remove 以及你已经有 char
    • 我不会推荐这个。 list pop 是 O(N) 而你的答案是 O(N^2) 复杂度。 Matt 和我的答案都运行在 O(N)
    【解决方案4】:

    更新版本:

    s1 = 可能包含 s2 的乱码

    s2 = 要搜索的单词

    步骤 1. 找到 s2 的集合

    第 2 步。遍历 s2 集合的每个字母。让我们将每个字母称为 s

    步骤 3. 对于每个字母 s,找出它在 s1 和 s2 中出现的次数

    步骤4:如果s2中的字母数

    步骤 5:如果 s2 集合中的所有字母都满足步骤 4 的条件,则 s2 在 s1 中。你可以返回True

    代码如下:

    def scramble_check(s1,s2):
        return True if all(s2.count(s) <= s1.count(s) for s in set(s2)) else False
    
    print (scramble_check('rkqodlw', 'world'))
    print (scramble_check('moonshine', 'moon'))
    print (scramble_check('strain', 'brain'))
    print (scramble_check('aaaappppleeeset', 'apple'))
    print (scramble_check('braintrain', 'rabbit'))
    

    以上代码的输出为:

    True
    True
    False
    True
    False
    

    杰斯,为了让你明白那一行代码,我扩展了函数。这是更扩展的版本。

    def scramble_check(s1,s2):
        ss = set(s2)  #create a set from word s2
        
        for s in ss: #iterate through each letter in set ss
    
            #compare count of occurrences of s in both s1 and s2
            #if s2 count is more than s1, then the word cannot be made with s1
            #so return False and exit the function
            if s2.count(s) > s1.count(s): return False
    
        #if we iterated through all of ss and each letter met the condition, then s2 can be created using s1. So return True
        return True
    

    所有这些都是一行:

    return True if all(s2.count(s) <= s1.count(s) for s in set(s2)) else
    

    【讨论】:

    • 是的,可以的——我总是忘记 str.count 函数的存在。您可能可以直接返回 all(...) 而不是执行条件。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-03
    • 2023-01-27
    • 2017-05-22
    • 2017-01-07
    • 2018-10-16
    • 1970-01-01
    • 2014-02-03
    相关资源
    最近更新 更多