如何使用分而治之的方法解决“固定大小的最大子数组”?

Posted

技术标签:

【中文标题】如何使用分而治之的方法解决“固定大小的最大子数组”?【英文标题】:How to solve "fixed size maximum subarray" using divide and conquer approach? 【发布时间】:2017-02-19 08:35:44 【问题描述】:

免责声明:我知道这个问题可以通过数组的单次传递非常有效地解决,但我对分而治之很感兴趣,因为它与我们用分治解决的典型问题有点不同并征服。

假设给定一个大小为 n、区间长度为 l 的浮点数组 X[1:n]。问题是设计一种分治算法,从和最大的数组中找出长度为 l 的子数组。

这就是我想出的。对于长度为 n 的数组,有 l 个连续元素的 n-l+1 个子数组。例如长度为 n = 10 和 l = 3 的数组,将有 8 个长度为 3 的子数组。

现在,为了将问题分成两半,我决定在 n-l+1/2 处拆分数组,以便将相等数量的子数组分配到我划分的两半,如下面的算法所示。同样,对于 n = 10,l = 3,n-l+1 = 8,所以我将问题划分为 (n-l+1)/2 = 4。但是对于第 4 个子数组,我需要最多的数组元素6 即 (n+l-1)/2.

void FixedLengthMS(input: X[1:n], l, output: k, max_sum)

   if(l==n)//only one sub-array
      sum = Sumof(X[1:n]);
      k=1;
   
   int kl, kr;
   float sum_l, sum_r;
   FixedLengthMS(X[1:(n+l-1)/2], l, kl, sum_l);
   FixedLengthMS(X[(n-l+3)/2:n], l, kr, sum_r);

   if(sum_l >= sum_r)
      sum = sum_l;
      k = kl;
   
   else
      sum = sum_r;
      k = n-l+1/2 + kr;
   

注意:清除数组索引 对于从 (n-l+1)/2 开始的子数组,我们需要数组元素直到 (n-l+1)/2 + l-1 = (n+l-1)/2

我的担心: 为了应用分而治之,我在两个数组中都使用了一些数据元素,因此我正在寻找另一种避免额外存储空间的方法。

将不胜感激更快的方法。

请忽略代码部分的语法,我只是想给出算法的概述。

【问题讨论】:

虽然最初的最大子数组问题实际上可以通过 D&C 很好地解决(这样做涉及计算,对于任何给定的间隔,不仅是该间隔中的最大子数组,还包括从左边缘开始的最大子数组间隔和最大子数组在右边缘结束;然后父问题可以使用其 2 个子问题的 3+3=6 个答案来计算其对这 3 个问题的答案),这个变体(即,长度 l 是固定的) ) 问题非常不适合 D&C。我不明白 O(n) 时间的 D&C 算法是如何可能的,除非你将 l 限制为 o(n)。 【参考方案1】:

您不需要分而治之。该任务可以使用简单的一次性算法。让我们假设,该数组足够大。那么:

double sum = 0;
for (size_t i = 0; i < l; ++i)
    sum += X[i];

size_t max_index = 0;
double max_sum = sum;

for (int i = 0; i < n - l; ++i) 
    sum += X[i + l] - X[i];
    if (sum > max_sum) 
        max_sum = sum;
        max_index = i;
    

【讨论】:

我知道,我可以通过数组的单次传递来做到这一点。我只是想知道如何使用分而治之的方法来做到这一点。无论如何感谢您的回答:) @BibekBhattarai 当你说固定大小的最大子数组时,你的意思是给定一个大小 l,其中 l

以上是关于如何使用分而治之的方法解决“固定大小的最大子数组”?的主要内容,如果未能解决你的问题,请参考以下文章

如何解决这个java方法中的***异常? [复制]

分而治之和快速排序

难以思考分而治之的方法

使用分而治之的最小前缀数组

使用分而治之的方法进行推理

使用分而治之的最大子阵列产品有人吗?