【问题标题】:Sliding window algorithm to calculate the list of all k-element contiguous subarray products of an array modulo p滑动窗口算法计算数组模 p 的所有 k 元素连续子数组乘积的列表
【发布时间】:2021-12-10 19:22:16
【问题描述】:

我有一个n 正整数数组。我想计算大小为kp 的所有连续子数组产品的列表。例如以下数组:

a = [3, 12, 5, 2, 3, 7, 4, 3]

使用k = 3p = 12,所有k 大小的连续子数组产品的有序列表将是:

k_products = [180, 120, 30, 42, 84, 84]

p 我们有:

k_products_p = [0, 0, 6, 6, 0, 0]

我们可以使用滑动窗口轻松计算k_products。我们所要做的就是计算第一个k 大小的子数组的乘积,然后使用以下公式计算k_product 的下一个元素:

k_product[i] = k_product[i - 1] * a[i + k] / a[i - 1]

在形成整个列表之后,我们可以为每个i 计算k_product[i] % p 以得到k_product_p。而已。 O(n) 复杂度还不错。

但是如果a[i]的元素很大,k_product的元素可能会溢出,因此我们无法计算k_product_p。另外,我们不能做以下事情:

k_product[i] = ((k_product[i - 1] % p) * (a[i + k] % p) / (a[i - 1] % p)) % p // incorrect

那么有没有一种快速算法可以做到这一点?请注意,p 不一定是素数,也不一定是 a 的元素的互质数。

编辑:如 cmets 中所述,python 中不会溢出,但处理非常大的数字会很耗时。

【问题讨论】:

  • 在某些情况下,先除后乘可能会有所帮助
  • 在Python中,我相信应该没有overflow的问题。一些关于此的帖子stackoverflow.com/questions/538551/…
  • 你是对的。但我认为复杂性会非常混乱。 @DanielHao
  • 这是为什么呢? ~...complexity will be quite messy?您仍然可以使用滑动窗口技术。解决它。对吗?
  • 是的,但 python 可能必须处理 100 位数字。我不认为这将是一个快速的解决方案。内存是另一个问题。 @DanielHao

标签: python arrays algorithm sliding-window modular-arithmetic


【解决方案1】:

这不是滑动窗口算法,但它是一种简单有效的方法,可以在 O(n) 时间内解决这个问题,无需任何除法:

让 A 成为您的原始数组。我们将想象在 A 的每个第 k 个元素上都有一个“标记”——元素 A[0]、A[k]、A[2k] 等。这确保了 A 中的每个 k 长度窗口都包含 正好一个标记。

现在,创建两个新数组 B 和 C,这样:

  • 在数组 B 中,每个元素 B[i] 将包含 A[i] 的乘积 (mod p) 以及直到 但不包括 下一个标记的所有后续元素。如果标记了 A[i],则 B[i] = 1。您可以从 i=n-1 到 i=0 单次反向计算。

  • 在数组 C 中,每个元素 C[i] 将包含 A[i] 的乘积 (mod p) 和所有前面的元素,直到 并包括 前面的标记。如果 A[i] 被标记,则 C[i] = A[i]。您可以从 i=0 到 i=n-1 一次向前计算。

现在,您可以轻松地计算任意 k 长度窗口在恒定时间内的完全乘积,因为 A[i]...A[i+k-1] 中任意窗口的乘积只是 B [i] * C[i+k-1]。请记住,窗口内只有一个标记。 B[i]是标记前元素的乘积,C[i+k-1]是标记后元素的乘积。

【讨论】:

  • 这既鼓舞人心又具有教育意义。感谢发帖!
  • 我从没想过除了滑动窗口之外的任何算法。但这一个简单而天才。谢谢!
猜你喜欢
  • 2021-12-02
  • 1970-01-01
  • 2015-12-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-12
  • 1970-01-01
  • 2016-01-01
  • 1970-01-01
相关资源
最近更新 更多