如何找到具有最小k长度和最大和的子数组?
Posted
技术标签:
【中文标题】如何找到具有最小k长度和最大和的子数组?【英文标题】:How to find a subarray with minimum k length and maximum sum? 【发布时间】: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 标准。 (见***.com/q/737240/416574) @pstrjds 我知道,但我的编译器 (Gcc) 支持它,所以为什么不使用它! 我并不是说不要使用它 :) 我只是想指出它以防其他人看到它并对他们的编译器感到沮丧,因为它无法编译。 Subset Sum 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;
【讨论】:
以上是关于如何找到具有最小k长度和最大和的子数组?的主要内容,如果未能解决你的问题,请参考以下文章
LintCode Python 简单级题目 最小子数组和最大子数组和
2021-07-16:三个无重叠子数组的最大和。给定数组 nums 由正整数组成,找到三个互不重叠的子数组的最大和。每个子数组的长度为k,我们要使这3*k个项的和最大化。返回每个区间起始索引的列表(索