C++ 指定最小长度的线性时间最大连续子序列和算法

C++ 指定最小长度的线性时间最大连续子序列和算法,c++,algorithm,C++,Algorithm,我有一个线性时间最大连续子序列和算法,它假设最小子序列长度仅为0: int maxSubSum4(const vector<int> & a, const int &minSeq) { int maxSum = 0, thisSum = 0; for (int j = 0; j < a.size(); j++) { thisSum += a[j]; if (thisSum > maxSum)

我有一个线性时间最大连续子序列和算法,它假设最小子序列长度仅为0:

int maxSubSum4(const vector<int> & a, const int &minSeq)
{
    int maxSum = 0, thisSum = 0;

    for (int j = 0; j < a.size(); j++)
    {
        thisSum += a[j];

        if (thisSum > maxSum)
            maxSum = thisSum;
        else if (thisSum < 0)
            thisSum = 0;
    }

    return maxSum;
}
int-maxSubSum4(常量向量&a、常量int&minSeq)
{
int maxSum=0,thisSum=0;
对于(int j=0;jmaxSum)
maxSum=此Sum;
else if(此总和<0)
此和=0;
}
返回最大和;
}

关于如何将其更新以处理用户指定的正最小子序列长度(
minSeq
)的任何提示?我完全被难住了。

创建一个
minSeq
长度和数组,这将是您的下限:

int maxSubSum5(const vector<int> & a, const int &minSeq){
  if(minSeq > a.size()) throw logic_error("maxSubSum5 - minSeq too big!");
  if(minSeq == 0) return maxSubSum4(a, minSeq);

  vector<int> minimal(a.size()-minSeq+1);
  minimal[0] = 0;
  for(size_t i=0; i<minSeq; ++i) minimal[0] += a[i];
  for(size_t i=1; i<minimal.size(); ++i) {
    minimal[i] = minimal[i-1] - a[i-1] + a[i+minSeq-1];
  }

  int maxSum = minimal[0], currentSum = maxSum;
  for(size_t i=minSeq; i<a.size(); ++i){
    currentSum += a[i];
    if(currentSum < minimal[i-minSeq+1]) currentSum = minimal[i-minSeq+1];
    if(currentSum > maxSum) maxSum = currentSum;
  }
  return maxSum;
}

我认为当所有的数字都是负数的时候,它一开始就不起作用。@KelvinLai我真的相信你是对的。更新后的功能是否与提供不同最小子序列值的功能齐头并进?是的。处理最小子序列长度的逻辑对于您现在的代码和将来的代码可能不同。您需要修改您的算法…我认为您需要交换
if
else if
条件..试试这个@SwarnavaSarkar这是一个很好的资源,但如果我这样做,它似乎仍然无法处理数组中的所有负片。仍然不是最小子序列要求的解决方案。我喜欢莫希特·库马尔的解决方案。不过,我认为需要证明的主要问题是,如果我们“重置currentSum”,那么将其重置为最小值[I-minSeq+1]总是安全的,而不必再次尝试向左增长。位置i的任何解决方案要么使用[i-minSeq+1],要么不使用[i-minSeq+1],因此我们可以在每个类别中选择最佳解决方案并进行比较。在后一种情况下,解决方案必然是单长度minSeq解决方案。在前一种情况下,我们需要找到一个最大值的子序列,其长度>=minSeq+1,并在位置i处结束。。。。。。设x[j]是在位置i-1处结束的长度j序列的分数:那么我们想要的是所有j>=minSeq上的max(x[j]+a[i])。但是a[i]是固定的,因此这与所有j>=minSeq上的max(x[j])+a[i]相同,并且我们已经从位置i-1的最优解中知道了第一项。因此,在这种情况下,我们实际上不需要做任何进一步的扫描。@j_random_hacker,我没有提供括号中语句的证据,但很明显:假设
s
可以表示为
n | p
,其中
p
具有正和。然后,由于
s
本身具有负和,
n
具有负和。但是我们会在更早的时候(当我们的序列是
n | | |(minSeq元素)
时)将其切断-但是我们没有,这是一个矛盾。因此,
s
的任何尾部都具有负和,
s
可以安全地丢弃。
int maxSubSum5(const vector<int> & a, const int &minSeq){
  if(minSeq > a.size()) throw logic_error("maxSubSum5 - minSeq too big!");
  if(minSeq == 0) return maxSubSum4(a, minSeq);

  int minimalSum = 0;
  for(size_t i=0; i<minSeq; ++i) minimalSum += a[i];

  int maxSum = minimalSum, currentSum = minimalSum;
  for(size_t i=minSeq; i<a.size(); ++i){
    currentSum += a[i];
    minimalSum += a[i] - a[i-minSeq];
    if(currentSum < minimalSum) currentSum = minimalSum;
    if(currentSum > maxSum) maxSum = currentSum;
  }
  return maxSum;
}