【问题标题】:Number of Subarray whose sum greater than given value总和大于给定值的子数组的数量
【发布时间】:2020-09-27 05:53:51
【问题描述】:

给定一个由N个整数组成的数组(正数和负数),找出总和大于或等于K的连续子数组的个数(另外,正面或负面)

我已经设法制定了一个简单的 O(N2) 解决方案,是否有可能变得更好?

【问题讨论】:

  • 星星有什么用?
  • 子数组必须是连续的吗?
  • @jasonN 哎呀。错字。会解决这个问题
  • @Imran 是的。将其添加到问题中

标签: algorithm data-structures


【解决方案1】:

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

  1. 让我们来看看前缀和。 (L, R] 子数组的总和是 prefixSum[R] - prefixSum[L]

  2. 表示我们可以统计LR的数量,即L < RprefixSum[R] - prefixSum[L] >= K,也就是prefixSum[L] <= prefixSum[R] - K

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

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

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

这是这个解决方案的伪代码:

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)元素个数的加法和计数操作,每一个都可以在O(log n)中完成。

【讨论】:

  • 这是一个了不起的解决方案。如果有人有这个的 Python 实现,请分享
【解决方案2】:

这是另一种解决方案,它使用分而治之的方法。时间复杂度为O(n lg n)

前两个步骤和上面的帖子一样:

  1. 创建前缀和,我们称它们为prefixSum[]

  2. 这意味着我们必须计算LR的数量,L &lt; RprefixSum[R] - prefixSum[L] &gt;= K

  3. 现在,让我们创建另一个数组,我们称之为arr[],其中arr[i] = prefixSum[N - 1 - i] 代表i0N - 1。这意味着我们正在创建一个反向的prefixSum[] 数组。

现在我们必须计算 ij 以及 i &lt; jarr[i] - arr[j] &gt;= K 的数量。为此,我们将使用 Merge Sort(使用 D & C 方法):

假设我们有:

MergeSort(arr, left, right):
    mid = (left + right) / 2
    MergeSort(arr, left, mid)
    MergeSort(arr, mid + 1, right)
    Merge(arr, left, mid, right)

Merge函数中,我们必须添加这个:

i = left - mid       # Index for the left array
j = mid + 1 - right  # Index for the right array

if (arr[i] >= arr[j]):
    if (arr[i] >= arr[j] + K):
        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:
    if (arr[i] >= arr[j] + K): # K can be negative.
        count += mid - i + 1;

这个思路和在数组中计算倒数是一样的
https://www.cdn.geeksforgeeks.org/counting-inversions/

【讨论】:

    猜你喜欢
    • 2016-05-27
    • 2014-08-07
    • 1970-01-01
    • 2023-04-06
    • 2022-10-12
    • 2020-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多