【问题标题】:How to find a subarray with minimum k length and maximum sum?如何找到具有最小k长度和最大和的子数组?
【发布时间】:2012-10-22 18:18:29
【问题描述】:

子数组包含正数和负数。你必须找到一个最大和子数组,使得子数组的长度大于或等于k。

这是我使用 Kadane 算法的 c++ 代码。

#include <iostream>

using namespace std;

int main(){

    int n,k;
    cin >> n >> k;
    int array[n];
    int sum = 0;
    int maxsum = 0;
    int beststarts[n];

    for(int i = 0;i < n; i++){
            cin >> array[i];
    }

    for(int i = 0;i < k-1;i ++){
            sum = sum+array[i];
            beststarts[i] = 0;
    }


    for(int i =  k-1;i < n; i++){ //best end search with min length;
            sum = sum+array[i];
            int testsum = sum;
            if(i > 0){
            beststarts[i] = beststarts[i-1];
            }
            for(int j = beststarts[i] ;i-j > k-1;j ++){
                    testsum = testsum - array[j];
                    if(testsum > sum){
                            beststarts[i] = j+1;
                            sum = testsum;
                    }
            }
            if(sum > maxsum){
                    maxsum = sum;
            }
    }

    cout << maxsum;

    return 0;
}

我的代码运行良好,但速度很慢,我想不出任何方法来改进我的代码。我也读过这个问题Find longest subarray whose sum divisible by K 但这不是我想要的,长度也可以大于k。

【问题讨论】:

  • 作为旁注。这不是有效的 C++。 C++ 不允许声明具有非常量值的数组。这是一些 C++ 编译器选择支持的 C99 标准。 (见stackoverflow.com/q/737240/416574
  • @pstrjds 我知道,但我的编译器 (Gcc) 支持它,所以为什么不使用它!
  • 我并不是说不要使用它 :) 我只是想指出它以防其他人看到它并对他们的编译器感到沮丧,因为它无法编译。
  • Subset Sum algorithm的可能重复

标签: c++ algorithm dynamic-programming kadanes-algorithm


【解决方案1】:

基于this answer的解决方案

Live demo

#include <algorithm>
#include <iterator>
#include <iostream>
#include <numeric>
#include <ostream>
#include <utility>
#include <vector>

// __________________________________________________

template<typename RandomAccessIterator> typename std::iterator_traits<RandomAccessIterator>::value_type
max_subarr_k(RandomAccessIterator first,RandomAccessIterator last,int k)
{
    using namespace std;
    typedef typename iterator_traits<RandomAccessIterator>::value_type value_type;
    if(distance(first,last) < k)
        return value_type(0);
    RandomAccessIterator tail=first;
    first+=k;
    value_type window=accumulate(tail,first,value_type(0));
    value_type max_sum=window, current_sum=window;
    while(first!=last)
    {
        window += (*first)-(*tail) ;
        current_sum = max( current_sum+(*first), window );
        max_sum = max(max_sum,current_sum);
        ++first;
        ++tail;
    }
    return max_sum;
}

// __________________________________________________

template<typename E,int N>
E *end(E (&arr)[N])
{
    return arr+N;
}

int main()
{
    using namespace std;
    int arr[]={1,2,4,-5,-4,-3,2,1,5,6,-20,1,1,1,1,1};
    cout << max_subarr_k(arr,end(arr),4) << endl;
    cout << max_subarr_k(arr,end(arr),5) << endl;
}

输出是:

14
11

【讨论】:

    【解决方案2】:
      int w(0);
        for (int i=0; i < k; i++) w += a[i];
        int run_sum(w), max_sum(w);
        for (int i=k; i < n; i++) {
                  w = a[i] + max(w, w-a[i-k]); //  window will such that it will include run_sum
                  run_sum = max(run_sum + a[i], w);
                  max_sum = max(run_sum, max_sum); 
        }
        return max_sum; 
    

    【讨论】:

      猜你喜欢
      • 2022-11-30
      • 2019-12-25
      • 2019-02-12
      • 2016-12-20
      • 2020-04-29
      • 2022-12-12
      • 2023-01-25
      • 2017-03-16
      • 2020-11-11
      相关资源
      最近更新 更多