求和范围内的子数组数

Number of subarrays within a sum range

问题
给定一个非负整数数组 A 和一个范围 (B, C), 找出数组中总和 S 在 [B, C] 或 B <= S <= C

范围内的连续子序列的数量

连续子序列定义为所有数字A[i], A[i + 1], .... A[j] 其中 0 <= i <= j < size(A)

示例:

A : [10, 5, 1, 0, 2]
(B, C) : (6, 8)

ans = 3
[5, 1], [5, 1, 0], [5, 1, 0, 2] 是仅有的 3 个连续子序列,其总和在 [6, 8]

范围内

我的代码

def numRange(A, B, C):

    n = len(A)
    count = 0
    for i in xrange(n-1):

        newsum = A[i]

        j = i + 1
        while newsum <= C and j < n:

            if newsum >= B :
                count += 1
            newsum += A[j]
            j += 1
    if A[n-1] >= B and A[n-1] <= C:
        count += 1
    return count

问题:答案错误。

  1. 我遗漏了哪些案例?
  2. 这段代码整改后如何提高效率?

服从

def numRange(A, B, C):
    n = len(A)
    sets = []

    for i in range(n):
        sum = 0
        j = i

        while sum < B and j < n:
            sum += A[j]
            j += 1

        while sum >= B and sum <= C and j <= n:
            if sum <= C:
                sets.append(A[i:j])
            if j < n:
                sum += A[j]
            j += 1

    return sets

sets = numRange([10, 5, 1, 0, 2], 6, 8)
print len(sets) # 3
print sets # [[5, 1], [5, 1, 0], [5, 1, 0, 2]]

我使用的策略是有效地缓冲结果,直到我到达终点,然后处理缓冲区的剩余部分。因此,这最多需要两次迭代或 O(n) 时间。

编辑:删除了对 sum():

的调用
def numRange(A, B, C):

    current = []
    current_sum = 0
    count = 0

    for number in A:
        current.append(number)
        current_sum += number
        while current_sum > C:
            current_sum -= current[0]
            current = current[1:]

        if B <= current_sum <= C:
            count += 1
            print current_sum, current

    # Now check the remaining items in current, in case of a trailing sequence:
    # Test with A = [10, 5, 1, 0, 2, 4] to demonstrate the need.
    if not current:
        return count

    current_sum -= current[0]    
    current = current[1:]
    while (B <= current_sum <= C):
        count += 1
        print current_sum, current
        current_sum -= current[0]
        current = current[1:]

    return count


print "Total of %d subarrays" % numRange( [10, 5, 1, 0, 2], 6, 8)
print
print "Total of %d subarrays" % numRange( [10, 5, 1, 0, 2, 4], 6, 8)

输出:

6 [5, 1]
6 [5, 1, 0]
8 [5, 1, 0, 2]
Total of 3 subarrays

6 [5, 1]
6 [5, 1, 0]
8 [5, 1, 0, 2]
7 [1, 0, 2, 4]
6 [0, 2, 4]
6 [2, 4]
Total of 6 subarrays

您的代码的问题是针对 [5, 1, 0, 2] 的情况。您计算等于 8 的总和。然后将 j 递增到 5

newsum += A[j] # newsum was 6, add A[4] = 2, now 8
j += 1

但随后循环退出,因为 j 现在等于 5,j < n 条件失败。因此,对于这个总和,计数的增量永远不会发生。不幸的是,仅仅改变内循环中事物的顺序不足以修复它。

这是我的 O(n^2) 最坏情况解决方案。额外的 O(1) space。谁能在 O(n)

中给出比这更好的解决方案
class Solution:
    def numRange(self, A, B, C):
        count = 0
        end = len(A)-1
        tot = 0
        temp_sum = 0
        temp_array = []
        tot_sum = sum(A[0:len(A)])
        for i in range(len(A)):
            current_sum = 0
            for j in range(i,len(A)):
                current_sum += A[j]
                if(current_sum > C):
                    break
                elif(B <= current_sum <= C):
                    #print current_sum
                    tot += 1
            tot_sum -= A[i]
            if(tot_sum < B):
                break
        return tot