如何解决在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)
尽管这会返回正确的结果,但这是一种特殊情况,对一般情况没有特别帮助。在大多数情况下,s
和t
会有所不同;并且当它们相等时,用于计算它们的共享字母数量的逻辑也应该起作用。
算法逻辑错误
此行代码高度可疑:
lc = [count(s[x],t) for x in range(len(t))]
首先,x
在t
的长度范围内,但是用作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
的第二个t
在min(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。
递归方法 复杂度分析:进行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 举报,一经查实,本站将立刻删除。