【问题标题】:Number of subarrays within a sum range总和范围内的子数组数
【发布时间】:2015-07-03 16:14:38
【问题描述】:

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

连续子序列被定义为所有数 A[i], A[i + 1], .... A[j] 其中 0

例子:

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. 这段代码改正后如何提高效率?

【问题讨论】:

    标签: python performance number-theory


    【解决方案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
    

    【讨论】:

    • 随着A 的增长,不断对current 的元素进行重新求和会变得昂贵。
    • 同意。但是可以通过存储总和并从中添加或减去元素值来优化该方法。我的目标是演示一个可行的算法。
    • 编辑删除对sum的调用
    • 度假回来查看我们答案中的 cmets...虽然提出了有效点,但此处使用的快捷方式使其对于分离的序列失败,例如 [10, 5, 1, 0, 2, 4, 99, 1, 2, 3, 4, 5]跨度>
    • 你是对的。如果要保持效率,这可能需要对算法进行细微的更改。
    【解决方案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^2),因为它有效地测试了每个可能的有效子序列。
    • 代码可能没有最好的时间复杂度,但它工作得很好。谢谢@mike.k
    【解决方案3】:

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

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

    但随后循环退出,因为 j 现在等于 5,不满足 j

    【讨论】:

      【解决方案4】:

      这是我的 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
      

      【讨论】:

      • 我发现这个答案既不相关也不有用。由于您的查询与我的不同,我认为您应该提出一个新问题,而不是破坏这个提要。
      • 这是您问题的答案。而且我敢肯定@Moshe 的代码在很多情况下都会失败。
      猜你喜欢
      • 1970-01-01
      • 2013-08-03
      • 2015-08-25
      • 2016-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-06
      相关资源
      最近更新 更多