Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/277.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 求和等于m的子串的个数_Python - Fatal编程技术网

Python 求和等于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,

我正在尝试一些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,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和操纵表达式字符串也会导致代码混乱。评论不错!