总和范围内的子阵列数

时间:2015-07-03 16:14:39

标签: python performance number-theory

问题
给定一组非负整数A和一个范围(B,C), 找到数组中连续子序列的数量,其中和S在[B,C]或B <= S <= C

的范围内

连续子序列定义为所有数字A [i],A [i + 1],.... A [j] 其中0 <= i&lt; = j&lt;尺寸(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. 如何在纠正之后提高此代码的效率?

4 个答案:

答案 0 :(得分:1)

让它服从

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]]

答案 1 :(得分:1)

我使用的策略是有效地缓冲结果,直到我结束,然后处理缓冲区的剩余部分。因此,这最多需要两次迭代,或者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

答案 2 :(得分:1)

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

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

然后循环退出,因为j现在等于5,j&lt; n条件。所以计数的增量永远不会发生在这个总和上。不幸的是,只是在内循环中切换事物的顺序并不足以解决它。

答案 3 :(得分:1)

这是我的O(n ^ 2)最坏情况解决方案。有O(1)额外空间。任何人都可以在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