总和大于给定值的子阵列数

时间:2015-02-01 22:42:19

标签: algorithm data-structures

给定一个 N 整数数组(正数和负数),找到连续子数组的数量,其总和大于或等于 K(同样,正面或负面的)

我设法制定了一个天真的O(N 2 )解决方案,是否有可能变得更好?

2 个答案:

答案 0 :(得分:5)

是的,可以在O(n log n)时间内完成。

  1. 让我们来看看前缀总和。 (L, R]子阵列的总和为prefixSum[R] - prefixSum[L]

  2. 这意味着我们可以计算LR的{​​{1}}和L < R的数量,这意味着prefixSum[R] - prefixSum[L] >= K

  3. 让我们从左到右迭代前缀和数组,并维护一个可以有效执行以下操作的数据结构:

    • 添加新元素。
    • 查找小于或等于给定数字的元素数。

    为此,我们可以使用平衡的二叉搜索树。

  4. 以下是此解决方案的伪代码:

    prefixSum[L] <= prefixSum[R] - K

    时间复杂度为tree = an empty search tree result = 0 // This sum corresponds to an empty prefix. prefixSum = 0 tree.add(prefixSum) // Iterate over the input array from left to right. for elem <- array: prefixSum += elem // Add the number of subarrays that have this element as the last one // and their sum is not less than K. result += tree.getNumberOfLessOrEqual(prefixSum - K) // Add the current prefix sum the tree. tree.add(prefixSum) print result ,因为有O(n log n)个添加和计算元素数量的操作,并且每个操作都可以在O(n)中完成。

答案 1 :(得分:0)

这是另一种解决方案,使用Divide and Conquer方法,时间复杂度为O(n lg n)。

前两个步骤就像上面的帖子一样。

  1. 创建前缀和,让我们调用prefixSum []数组。

  2. 这意味着我们必须计算L&lt; L&lt; R和prefixSum [R] - prefixSum [L]&gt; = K。

  3. 现在,让我们创建另一个数组,让我们称它为arr [],其中arr [i] = prefixSum [N-1-i]为i从0到N-1。

    我现在的工作是计算i&lt; i的数量。 j和arr [i] - arr [j]&gt; = K。

    为此,我们使用Merge Sort(使用D&amp; C方法):

     Suppose that we have MergeSort(arr,left,right) :
      ... mid = (left + right )/2 ...
        MergeSort(arr,left,mid);
        MergeSort(arr,mid+1,right);
        Merge(arr,left,mid,right);
    
     In Merge function, we add this :
     (i: index for the left array : left - mid , j: index for the right array: mid+1 - right)
    if (arr[i] >= arr[j] ) {
       if ( arr[i] >= arr[j] + K )
          count = count + ( mid - i + 1 ); /* because arr[] from i to mid 
          are all greater or equal to arr[i] so if arr[i]>= arr[j] + K then 
          arr[] from i to mid are all >= arr[j] + K .*/
        .....}
    else {  // arr[i]<arr[j] 
       if ( arr[i] >= arr[j] + K ) // K can be negative.
          count = count + ( mid - i + 1 );
        .....}
    

    在数组中计算Inversion的想法是一样的 https://www.cdn.geeksforgeeks.org/counting-inversions/