Python 求和等于m的子串的个数
我正在尝试一些python,我得到了: 我有一个字符串S='3,0,4,0,3,1,0,1,1,0,0,5,0,4,2',m=9。 我想知道有多少个和等于m的子串Python 求和等于m的子串的个数,python,Python,我正在尝试一些python,我得到了: 我有一个字符串S='3,0,4,0,3,1,0,1,1,0,0,5,0,4,2',m=9。 我想知道有多少个和等于m的子串 So with S and m above i whould get 7 as a result as: '3,0,4,0,3,1,0,1,0,1,0,0,5,0,4,2' _'0,4,0,3,1,0,1,0'_____________ _'0,4,0,3,1,0,1'_______________ ___'4,0,3,1,0,
So with S and m above i whould get 7 as a result as:
'3,0,4,0,3,1,0,1,0,1,0,0,5,0,4,2'
_'0,4,0,3,1,0,1,0'_____________
_'0,4,0,3,1,0,1'_______________
___'4,0,3,1,0,1,0'_____________
____'4,0,3,1,0,1'_______________
____________________'0,0,5,0,4'_
______________________'0,5,0,4'_
_______________________'5,0,4'_
现在,我想出的代码就是这样的
def es1(S,m):
c = 0
M = 0
ls = StringToInt(S)
for x in ls:
i= ls.index(x)
for y in ls[i+1:]:
M = x + y
if M == m:
c += 1
M = 0
break
if M > m:
M = 0
break
else:
continue
return c
def StringToInt(ls):
s = [int(x) for x in ls.split(',')]
return s
其中StringToInt obv为我提供了一个要处理的int列表。
我不明白的是,我的概念哪里是错的,因为es1返回3您的代码计算字符串S中有多少对数字,这些数字一起给出了m,而您实际上想要测试所有可能的子字符串 你可以这样做: 数字=[3,0,4,0,3,1,0,1,0,1,0,0,5,0,4,2] m=9 c=0 对于以数字表示的i: 对于范围-i中的j: 总和=0 对于k的数字[i:i+j]: 总和+=k 如果总和=m: c+=1 printc 输出:
7
您的代码计算字符串S中有多少对数字,这些数字加起来等于m,而您实际上想要测试所有可能的子字符串 你可以这样做: 数字=[3,0,4,0,3,1,0,1,0,1,0,0,5,0,4,2] m=9 c=0 对于以数字表示的i: 对于范围-i中的j: 总和=0 对于k的数字[i:i+j]: 总和+=k 如果总和=m: c+=1 printc 输出:
7
编辑!->这段代码实际上是所有可能的子集,而不是子列表。我将把这个问题留在这里,以防这个解决方案对任何访问这个问题的人都有帮助 这段代码得到了所有的解决方案。如果您查看函数es1,结果变量是包含所有可能解决方案的巨大数组列表
import itertools
def es1(S,m):
result = [seq for i in range(len(StringToInt(S)), 0, -1) for seq in itertools.combinations(StringToInt(S), i) if sum(seq) == m]
return len(result)
def StringToInt(ls):
s = [int(x) for x in ls.split(',')]
return s
print(es1("3,0,4,0,3,1,0,1,0,1,0,0,5,0,4,2", 9))
输出:
4608
7
有4608个可能的集合添加到值9。编辑!->这段代码实际上是所有可能的子集,而不是子列表。我将把这个问题留在这里,以防这个解决方案对任何访问这个问题的人都有帮助 这段代码得到了所有的解决方案。如果您查看函数es1,结果变量是包含所有可能解决方案的巨大数组列表
import itertools
def es1(S,m):
result = [seq for i in range(len(StringToInt(S)), 0, -1) for seq in itertools.combinations(StringToInt(S), i) if sum(seq) == m]
return len(result)
def StringToInt(ls):
s = [int(x) for x in ls.split(',')]
return s
print(es1("3,0,4,0,3,1,0,1,0,1,0,0,5,0,4,2", 9))
输出:
4608
7
有4608个可能的集合添加到值9。这是您要查找的代码。我觉得按位置看更适合这个问题,所以我做了,它成功了
def es1(S,m):
c = 0
M = 0
ls = StringToInt(S)
for i in range(0, len(ls)):
M = 0
for x in range(i, len(ls)):
M += ls[x]
if M == m:
c += 1
elif M >= m:
break
return c
def StringToInt(ls):
s = [int(x) for x in ls.split(',')]
return s
print(es1("3,0,4,0,3,1,0,1,0,1,0,0,5,0,4,2", 9))
输出:
4608
7
这就是你要找的密码。我觉得按位置看更适合这个问题,所以我做了,它成功了
def es1(S,m):
c = 0
M = 0
ls = StringToInt(S)
for i in range(0, len(ls)):
M = 0
for x in range(i, len(ls)):
M += ls[x]
if M == m:
c += 1
elif M >= m:
break
return c
def StringToInt(ls):
s = [int(x) for x in ls.split(',')]
return s
print(es1("3,0,4,0,3,1,0,1,0,1,0,0,5,0,4,2", 9))
输出:
4608
7
正如其他人提到的,您的代码只查看列表中元素对的总和。您需要查看子列表 这是一个关于复杂性的解决方案,即它是有效的,因为它只扫描列表一次:
def es2(s, m):
s = string_to_int(s)
c = 0
# index of left of sub-list
left = 0
# index of right of sub-list
right = 0
# running total of sublist sum
current_sum = 0
while True:
# if the sub-list has the correct sum
if current_sum == m:
# add as many zeros on the end as works
temp_current_sum = current_sum
for temp_right in range(right, len(s) + 1):
if temp_current_sum == m:
c += 1
if temp_right<len(s):
temp_current_sum += s[temp_right]
else:
break
if current_sum >= m:
# move the left end along and update running total
current_sum -= s[left]
left += 1
else:
# move the right end along and update running total
if right == len(s):
# if the end of the list is reached, exit
return c
current_sum += s[right]
right += 1
def string_to_int(ls):
s = [int(x) for x in ls.split(',')]
return s
if __name__ == '__main__':
print(es2('3,0,4,0,3,1,0,1,0,1,0,0,5,0,4,2', 9))
正如其他人提到的,您的代码只查看列表中元素对的总和。您需要查看子列表 这是一个关于复杂性的解决方案,即它是有效的,因为它只扫描列表一次:
def es2(s, m):
s = string_to_int(s)
c = 0
# index of left of sub-list
left = 0
# index of right of sub-list
right = 0
# running total of sublist sum
current_sum = 0
while True:
# if the sub-list has the correct sum
if current_sum == m:
# add as many zeros on the end as works
temp_current_sum = current_sum
for temp_right in range(right, len(s) + 1):
if temp_current_sum == m:
c += 1
if temp_right<len(s):
temp_current_sum += s[temp_right]
else:
break
if current_sum >= m:
# move the left end along and update running total
current_sum -= s[left]
left += 1
else:
# move the right end along and update running total
if right == len(s):
# if the end of the list is reached, exit
return c
current_sum += s[right]
right += 1
def string_to_int(ls):
s = [int(x) for x in ls.split(',')]
return s
if __name__ == '__main__':
print(es2('3,0,4,0,3,1,0,1,0,1,0,0,5,0,4,2', 9))
您可以使用zip将数字逐步添加到总和列表中,并计算每次传递的9数:
S = '3,0,4,0,3,1,0,1,0,1,0,0,5,0,4,2'
m = 9
numbers = list(map(int,S.split(",")))
result = 0
sums = numbers
for i in range(len(numbers)):
result += sums.count(m)
sums = [a+b for a,b in zip(sums,numbers[i+1:]) ]
print(result)
要获得更具功能性的编程方法,可以使用“从itertools累积”:
from itertools import accumulate
numbers = list(map(int,S.split(",")))
ranges = (numbers[i:] for i in range(len(numbers)))
sums = (accumulate(r) for r in ranges)
result = sum( list(s).count(m) for s in sums )
print(result)
为了解释这是如何工作的,让我们首先看看范围的内容,这些范围是从每个位置到列表末尾的子字符串:
[3, 0, 4, 0, 3, 1, 0, 1, 0, 1, 0, 0, 5, 0, 4, 2]
[0, 4, 0, 3, 1, 0, 1, 0, 1, 0, 0, 5, 0, 4, 2]
[4, 0, 3, 1, 0, 1, 0, 1, 0, 0, 5, 0, 4, 2]
[0, 3, 1, 0, 1, 0, 1, 0, 0, 5, 0, 4, 2]
[3, 1, 0, 1, 0, 1, 0, 0, 5, 0, 4, 2]
[1, 0, 1, 0, 1, 0, 0, 5, 0, 4, 2]
[0, 1, 0, 1, 0, 0, 5, 0, 4, 2]
[1, 0, 1, 0, 0, 5, 0, 4, 2]
[0, 1, 0, 0, 5, 0, 4, 2]
[1, 0, 0, 5, 0, 4, 2]
[0, 0, 5, 0, 4, 2]
[0, 5, 0, 4, 2]
[5, 0, 4, 2]
[0, 4, 2]
[4, 2]
[2]
当我们对行和进行累积求和时,我们获得从行号定义的位置开始的值的总和,以及从列号定义的长度开始的值的总和。e、 g.第5行第3列表示从第五个位置开始的3个值的总和:
[3, 3, 7, 7, 10, 11, 11, 12, 12, 13, 13, 13, 18, 18, 22, 24]
[0, 4, 4, 7, 8, 8, 9, 9, 10, 10, 10, 15, 15, 19, 21]
[4, 4, 7, 8, 8, 9, 9, 10, 10, 10, 15, 15, 19, 21]
[0, 3, 4, 4, 5, 5, 6, 6, 6, 11, 11, 15, 17]
[3, 4, 4, 5, 5, 6, 6, 6, 11, 11, 15, 17]
[1, 1, 2, 2, 3, 3, 3, 8, 8, 12, 14]
[0, 1, 1, 2, 2, 2, 7, 7, 11, 13]
[1, 1, 2, 2, 2, 7, 7, 11, 13]
[0, 1, 1, 1, 6, 6, 10, 12]
[1, 1, 1, 6, 6, 10, 12]
[0, 0, 5, 5, 9, 11]
[0, 5, 5, 9, 11]
[5, 5, 9, 11]
[0, 4, 6]
[4, 6]
[2]
在这个三角矩阵中,每个位置对应于一个可能的子串的和。我们只需要数一数9的数量就可以得到结果
上述解决方案将在^2时间内执行,但如果您关心性能,有一种方法可以使用字典按时获得结果。不必按照上述逻辑构建整个子数组,您只需计算每个和的位置总数。然后,对于每个位置的总和,直接转到前一个总和,该总和正好小于m,以获得该位置的子字符串数
from itertools import accumulate
from collections import Counter
numbers = map(int,S.split(","))
result = 0
sums = Counter([0])
for s in accumulate(numbers):
result += sums[s-m]
sums[s] += 1
print(result)
请注意,所有这些解决方案都支持列表中的负数以及负数或零目标。您可以使用zip将数字逐步添加到总和列表中,并计算每次传递的9数:
S = '3,0,4,0,3,1,0,1,0,1,0,0,5,0,4,2'
m = 9
numbers = list(map(int,S.split(",")))
result = 0
sums = numbers
for i in range(len(numbers)):
result += sums.count(m)
sums = [a+b for a,b in zip(sums,numbers[i+1:]) ]
print(result)
要获得更具功能性的编程方法,可以使用“从itertools累积”:
from itertools import accumulate
numbers = list(map(int,S.split(",")))
ranges = (numbers[i:] for i in range(len(numbers)))
sums = (accumulate(r) for r in ranges)
result = sum( list(s).count(m) for s in sums )
print(result)
为了解释这是如何工作的,让我们首先看看范围的内容,这些范围是从每个位置到列表末尾的子字符串:
[3, 0, 4, 0, 3, 1, 0, 1, 0, 1, 0, 0, 5, 0, 4, 2]
[0, 4, 0, 3, 1, 0, 1, 0, 1, 0, 0, 5, 0, 4, 2]
[4, 0, 3, 1, 0, 1, 0, 1, 0, 0, 5, 0, 4, 2]
[0, 3, 1, 0, 1, 0, 1, 0, 0, 5, 0, 4, 2]
[3, 1, 0, 1, 0, 1, 0, 0, 5, 0, 4, 2]
[1, 0, 1, 0, 1, 0, 0, 5, 0, 4, 2]
[0, 1, 0, 1, 0, 0, 5, 0, 4, 2]
[1, 0, 1, 0, 0, 5, 0, 4, 2]
[0, 1, 0, 0, 5, 0, 4, 2]
[1, 0, 0, 5, 0, 4, 2]
[0, 0, 5, 0, 4, 2]
[0, 5, 0, 4, 2]
[5, 0, 4, 2]
[0, 4, 2]
[4, 2]
[2]
当我们对行和进行累积求和时,我们获得从行号定义的位置开始的值的总和,以及从列号定义的长度开始的值的总和。e、 g.第5行第3列表示从第五个位置开始的3个值的总和:
[3, 3, 7, 7, 10, 11, 11, 12, 12, 13, 13, 13, 18, 18, 22, 24]
[0, 4, 4, 7, 8, 8, 9, 9, 10, 10, 10, 15, 15, 19, 21]
[4, 4, 7, 8, 8, 9, 9, 10, 10, 10, 15, 15, 19, 21]
[0, 3, 4, 4, 5, 5, 6, 6, 6, 11, 11, 15, 17]
[3, 4, 4, 5, 5, 6, 6, 6, 11, 11, 15, 17]
[1, 1, 2, 2, 3, 3, 3, 8, 8, 12, 14]
[0, 1, 1, 2, 2, 2, 7, 7, 11, 13]
[1, 1, 2, 2, 2, 7, 7, 11, 13]
[0, 1, 1, 1, 6, 6, 10, 12]
[1, 1, 1, 6, 6, 10, 12]
[0, 0, 5, 5, 9, 11]
[0, 5, 5, 9, 11]
[5, 5, 9, 11]
[0, 4, 6]
[4, 6]
[2]
在这个三角矩阵中,每个位置对应于一个可能的子串的和。我们只需要数一数9的数量就可以了
得到结果
上述解决方案将在^2时间内执行,但如果您关心性能,有一种方法可以使用字典按时获得结果。不必按照上述逻辑构建整个子数组,您只需计算每个和的位置总数。然后,对于每个位置的总和,直接转到前一个总和,该总和正好小于m,以获得该位置的子字符串数
from itertools import accumulate
from collections import Counter
numbers = map(int,S.split(","))
result = 0
sums = Counter([0])
for s in accumulate(numbers):
result += sums[s-m]
sums[s] += 1
print(result)
请注意,所有这些解决方案都支持列表中的负数以及负数或零目标。我不明白为什么要使用此循环结构,因为它允许对同一元素进行两次计数。这只是我想到的第一件事。但是i+1不应该解决这个问题吗,它应该每次从x之后的元素开始,对吗?如果你的目标数是6,那么这段代码在第一次迭代时就会找到一个解决方案,因为x和y都是3。但是这些元素是相同的,所以它是不正确的。列表中的所有元素都假定为正吗?如果它们都是正的,你可以比允许负的更快地解决问题。是的,只有正的。我不明白你为什么要使用这种循环结构,因为它允许同一元素被计数两次。这只是我想到的第一件事。但是i+1不应该解决这个问题吗,它应该每次从x之后的元素开始,对吗?如果你的目标数是6,那么这段代码在第一次迭代时就会找到一个解决方案,因为x和y都是3。但是这些元素是相同的,所以它是不正确的。列表中的所有元素都假定为正吗?如果它们都是正的,你可以得到比允许负的更快的解是的,只有正的它不应该返回3,因为没有一对等于9等等,我不明白,我以为你想找到等于9的像集,而不仅仅是对。还有一个piar等于9,5+4是等于9的一对有两个4和一个5给出三对4+5是的,我想要这些集合。它不应该返回3,因为没有一对等于9的集合等等,我不明白,我以为你想找到等于9的集合,而不仅仅是对。还有一个等于9的piar,5+4是等于9的一对,有两个4和一个5给出了三对4+5是的,我想要集合。这是所有子集的组合,而不是所有子列表。好吧,兄弟,让我想一想。好吧,伙计,如果你看看我的另一个答案,它完全符合你的要求。这是所有子集的组合,而不是所有子列表。好吧,兄弟,让我想一想。好吧,伙计,如果你看看我的另一个答案,它完全符合你的要求。我认为它不应该是我在rangem中,因为它寻找长度为m的子列表的总和。由于列表中允许零,因此可能存在长度大于m且总和为m的子列表。一个失败的例子:S='1,0,0,1',m=2@Oli,你说得对,这是一系列的数字。那是我的错误。现在修复了它。我认为它不应该用于rangem中的I,因为它查找长度为m的子列表的总和。由于列表中允许零,因此可能存在长度大于m且总和为m的子列表。一个失败的例子:S='1,0,0,1',m=2@Oli,你说得对,这是一系列的数字。那是我的错误。现在已修复。虽然在这种情况下使用eval应该是安全的,但通常是不安全的,不需要解决此问题。使用eval和操纵表达式字符串也会导致代码混乱。评论不错!虽然在这种情况下使用eval应该是安全的,但它通常是不安全的,并且没有必要解决这个问题。使用eval和操纵表达式字符串也会导致代码混乱。评论不错!