长度为K的滑动窗口的最大元素之和

麦克风

最近,我陷入了一个问题。该算法的一部分需要计算长度为K的滑动窗口的最大元素之和其中K的范围是1 <= K <= N(数组的N个长度)。

例如,如果我有一个数组A作为5,3,12,4
长度为1的5 + 3 + 12 + 4 = 24
滑动窗口:长度为2的5 + 12 + 12 = 29
滑动窗口:长度为3的12 + 12 = 24
滑动窗口:长度为4的滑动窗口:12

Final answer is 24,29,24,12

我已经尝试过这个O(N ^ 2)对于每个长度为K的滑动窗口,我可以计算出O(N)的最大值。由于K高达N。因此,总体复杂度变为O(N ^ 2)
我正在寻找O(N)O(NlogN)或与此算法类似的东西,例如N可能高达10 ^ 5。
注意:数组中的元素可以大到10 ^ 9,因此输出的最终答案为模10 ^ 9 + 7

编辑:我实际上想为总体上每个K值(即从0到N)找到答案线性时间或O(NlogN),而不是O(KN)或O(KNlogN),其中K = {1,2,3,.... N}

大卫·艾森斯塔

这是O(n)的略图。

对于每个元素,确定左边的连续元素不多(称为a),右边的相邻元素少(称为this b)。可以针对时间为O(n)的所有元素完成此操作-请参阅MBo的答案。

如果窗口包含该元素,并且仅在a其左侧和b右侧的元素之中,则该元素在其窗口中最大有用的是,这种长度为k的窗口的数量(以及这些窗口的总贡献)在k中是分段线性的,最多为五个。例如,如果a = 5b = 3,则有

1 window  of size 1
2 windows of size 2
3 windows of size 3
4 windows of size 4
4 windows of size 5
4 windows of size 6
3 windows of size 7
2 windows of size 8
1 window  of size 9.

我们需要有效编码这一贡献的数据结构是一棵Fenwick树,其值不是数字而是k的线性函数。对于分段线性贡献函数的每个线性部分,我们在其间隔的开始将其添加到单元格中,然后从末尾的单元格中将其减去(封闭的起点,开放的终点)。最后,我们检索所有前缀总和,并在其索引k处对其求值,以获得最终数组。

(好吧,现在必须运行,但是我们实际上不需要第二步的Fenwick树,这将复杂度降低到O(n),并且也许还有一种方法可以在线性时间内进行第一步)

Python 3,经过轻松测试:

def left_extents(lst):
  result = []
  stack = [-1]
  for i in range(len(lst)):
    while stack[-1] >= 0 and lst[i] >= lst[stack[-1]]:
      del stack[-1]
    result.append(stack[-1] + 1)
    stack.append(i)
  return result


def right_extents(lst):
  result = []
  stack = [len(lst)]
  for i in range(len(lst) - 1, -1, -1):
    while stack[-1] < len(lst) and lst[i] > lst[stack[-1]]:
      del stack[-1]
    result.append(stack[-1])
    stack.append(i)
  result.reverse()
  return result


def sliding_window_totals(lst):
  delta_constant = [0] * (len(lst) + 2)
  delta_linear = [0] * (len(lst) + 2)
  for l, i, r in zip(left_extents(lst), range(len(lst)), right_extents(lst)):
    a = i - l
    b = r - (i + 1)
    if a > b:
      a, b = b, a
    delta_linear[1] += lst[i]
    delta_linear[a + 1] -= lst[i]
    delta_constant[a + 1] += lst[i] * (a + 1)
    delta_constant[b + 2] += lst[i] * (b + 1)
    delta_linear[b + 2] -= lst[i]
    delta_linear[a + b + 2] += lst[i]
    delta_constant[a + b + 2] -= lst[i] * (a + 1)
    delta_constant[a + b + 2] -= lst[i] * (b + 1)
  result = []
  constant = 0
  linear = 0
  for j in range(1, len(lst) + 1):
    constant += delta_constant[j]
    linear += delta_linear[j]
    result.append(constant + linear * j)
  return result

print(sliding_window_totals([5, 3, 12, 4]))

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何在O(n)中长度为n的未排序数组中找到第k个最大元素?

“稳定” k最大元素算法

在TensorFlow中将张量的k个最大元素设置为零

仅使用队列查找大小为 K 的所有连续子数组中的最大元素

给定n个正整数的序列,请找到长度为k的子序列,以使差的绝对值之和最大

数组的K个最大元素,排序算法

返回最大元素

子序列的最大长度,以使得每个连续元素的按位XOR为k

树中的最大元素

区域中的最大元素

偏序最大元素

映射中的最大元素

查找最大元素的索引

数组中的最大子集,使得最小和最大元素的间距小于K

给定一个大小为n的整数数组,找到第k个最大元素而不对整个数组进行排序

滑动窗口的最大值为O(n)时间

通过快速选择获得第 k 个最大元素

在未排序的对数组中查找 K 个唯一最大元素

向数组中插入绝对差后,找到数组中的第k个最大元素

支持第k个最大元素快速查找的队列数据结构

使用堆查找第K个最大元素的时间复杂度

基於長度的數組中第 k 個最大元素(字符串)

Boolean 的解释 - 在未排序的数组中查找第 K 个最大元素

Java:使用2个数组查找数组的第K个最大元素

如何改进此代码以查找数组的 k 个最大元素?

在 Python 中使用 QuickSelect 查找第 K 个最大元素

使用快速选择算法查找第 k 个最大元素

如何在指数大列表中找到第 k 个最大元素?

查找一行最大元素总和为 c+ 的二维数组