具有给定元素数的最大子阵列

时间:2014-12-28 11:22:45

标签: algorithm arrays

最大子阵列问题试图找到一维数组的连续子阵列,使得该子阵列的元素总和最大。它可以使用动态编程轻松解决。

但是,在存在附加约束的情况下,子阵列必须具有至少k个元素。有没有解决它的O(n)或O(n * logn)算法?

1 个答案:

答案 0 :(得分:1)

您可以使用Sliding Window算法。

让我们举个例子:

Original array : 4 -2 6 -10 13 8
Window size    : k = 3
maximum = -inf

在每次迭代中,您必须计算当前窗口的值并检查它是否是最大值。

1st window is : |4 -2 6| -10 13 8  
window sum = 8  
maximum = max(-inf , 8) = 8

第一个窗口总和必须通过一个带O(k)

的简单循环来计算

第二个窗口会发生什么?如您所见,如果您只是减去上一个窗口的第一个元素并将新值添加到总和中,则可以获得第二个窗口的总和。那就是:

2nd window is : 4 |-2 6 -10| 13 8  
Window sum = 8 - 4 + (-10) = -6  
maximum = max(8 , -6) = 8

...类似

3rd window is : 4 -2 |6 -10 13| 8  
Window sum = -6 - (-2) + 13 = 9  
maximum = max(8 , 9) = 9

4th window is : 4 -2 6 |-10 13 8|  
Window sum = 9 - 6 + 8 = 11  
maximum = max(9 , 11) = 11

所以答案是= 11

看,这个例子是针对固定的窗口大小。那就是如果问题是元素必须是k的最大总和。如果问题至少说k个元素。那些元素可能比k大,那么你必须做一些额外的工作:

  • 您必须存储上一个窗口的减去元素的总和
  • 如果减去的元素的总和变为负数,则将其设为0,否则保持原样
  • 每次计算maximum = max(current_max , sum)时都会将其更改为

    maximum = max(current_max , sum + subtracted_element's_sum)

这就是全部:)

复杂性:O(n)

C ++ 实施:

#include <bits/stdc++.h>
using namespace std;

int main(){
    int i,j,n,k,x,y;
    cin>>n>>k;
    vector<int>v;
    for(i=0; i < n; i++)
    {
        cin>>x;
        v.push_back(x);
    }
    int sum = 0, prev_sum = 0;
    for(i=0;i<k;i++) // Calculating sum of first window
      sum += v[i];
    int maximum = sum;
    for(i = 1; i + k <= n; i++)
    {
        sum = sum - v[i-1] + v[i+k-1]; // Calculating sum of the next windows
        prev_sum += v[i-1]; // Storing previous subtracted elements sum
        if(prev_sum < 0) // Checking if previous sum becomes negative. If so then make it 0, otherwise skip
          prev_sum = 0;
        maximum = max(maximum, sum + prev_sum); // Saving maximum window sum
    }
    cout<<maximum<<"\n";
}