微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在Python中递归计算字母字符串s和t的数量

如何解决在Python中递归计算字母字符串s和t的数量

我必须递归地或用列表理解来计算两个给定字符串的 lingo 得分。两个字符串共享一个永远的字母。

我尝试过这样做,但是只有在s [0]位于t的情况下才起作用,但是否则它不执行应有的作用,并且我看不到这里实际上出了什么问题。

def count(e,L):
    lc = [1 for x in L if x == e]
    return sum(lc)

def lingo(s,t):
    if s == '' or t == '':
        return 0
    elif s == t:
        return len(s)
    if s[0] in t:
        lc = [count(s[x],t) for x in range(len(t))]
        return sum(lc)
    else:
        #remove s[0] and try again
        lingo(s[:1],t)

这些断言与赋值有关:

assert lingo('diner','proza') == 1
assert lingo('beeft','euvel') == 2
assert lingo('gattaca','aggtccaggcgc') == 5
assert lingo('gattaca','') == 0 

解决方法

最明显的错误

您在代码的最后一行缺少return语句。代替:

    else:
        #remove s[0] and try again
        lingo(s[:1],t)

应该是:

    else:
        #remove s[0] and try again
        return lingo(s[:1],t)

代码中的冗余

以下代码段是不必要的:

    elif s == t:
        return len(s)

尽管这会返回正确的结果,但这是一种特殊情况,对一般情况没有特别帮助。在大多数情况下,st会有所不同;并且当它们相等时,用于计算它们的共享字母数量的逻辑也应该起作用。

算法逻辑错误

此行代码高度可疑:

lc = [count(s[x],t) for x in range(len(t))]

首先,xt的长度范围内,但是用作s的索引。如果t长于s,这将立即引发IndexError异常。如果t短于s或与assert lingo('beeft','euvel') == 2 相同,那么它不会引发异常,但是很可能会返回错误的结果。

请注意提供的这个有趣的测试用例:

'e'

字母'beeft''euvel'中出现两次,在count(s[1],t) + count(s[2],t)中出现两次,结果为2。但是,如果您计算'e',则会发现值4。这这是因为s的第一个t'e'中被发现了两次,而s的第二个tmin(s.count(s[0]),t.count(s[0]))中也被发现了两次。

Janecx's answer提供了一种认真解决此问题的方法。您需要了解def lingo(s,t): s = sorted(s) # this doesn't modify the original string,it makes a local copy t = sorted(t) # this doesn't modify the original string,it makes a local copy result = 0 i = 0 j = 0 while (i < len(s) and j < len(t)): if s[i] == t[j]: result += 1 i += 1 j += 1 elif s[i] < t[j]: i += 1 else: j += 1 return result 背后的逻辑。

其他python解决方案

现在,您绝对要使用递归和列表推导。如果您对解决问题的其他方式感兴趣,可以使用以下不同的算法。

对字符串进行排序(排序是一种功能强大的工具,可轻松解决许多问题)

N log N + M log M

复杂度分析:排序采用import collections def lingo(s,t): return sum((collections.Counter(s) & collections.Counter(t)).values()) 个运算,其中N = len(s)和M = len(t)。整个while循环只需要N + M个操作;因为s和t以相同的顺序排序,所以速度很快,因此我们与s中的对应元素在同一时间到达s的元素,因此我们不需要将s的每个元素与t的每个元素进行比较

collections.Counter (专门用于计数事件的python对象)

N + M

复杂度分析:这需要进行&个运算,其中N = len(s)和M = len(t)。计数器只通过对s进行一次计数就可以简单地计算出s中每个字母的出现次数,而对t进行一次就可以计算t中每个字母的出现次数;然后min(...)操作将每个字母的两个计数保持最小值(让人想起Janecx的N * M操作);然后将所有计数相加。求和仅需进行与唯一字母一样多的操作,对于一个DNA序列,该字母为4。如果是字母,则为26;并且通常在ASCII / Latin-1字符串中最多为256。

来自Janecx's answer

递归方法 复杂度分析:进行TextField("Placeholder",text:$text.animation())个操作,其中N = len(s)和M = len(t)。这比其他两种方法要慢得多,因为对于s的每个元素,我们都需要遍历t的每个元素。迭代编写,这将是一个嵌套在第二个for循环内的for循环。

,

你去了。这段代码做什么?如果字符串之一为空,则返回0。在其他情况下,它找到s和t中s [0]的最小出现次数,然后使用递归计算s [1]的最小出现次数在没有第一个字符的t版本中,依此类推。

def lingo(s,t):
    if s == '' or t == '':
        return 0
    return min(s.count(s[0]),t.count(s[0])) + lingo(s[1:],t.replace(s[0],''))


assert lingo('diner','proza') == 1
assert lingo('beeft','euvel') == 2
assert lingo('gattaca','aggtccaggcgc') == 5
assert lingo('gattaca','') == 0

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。