原题:最大子列和
问题描述
“最大子列和”则被定义为所有连续子列元素的和中最大者。例如给定序列{ -2, 11, -4, 13, -5, -2 },其连续子列{ 11, -4, 13 }有最大的和20。现要求你编写程序,计算给定整数序列的最大子列和。
思路
穷举法 : 设置子列的left和right,列举出所有子列的情况,分别计算每个子列的和,进行比较求出最大值。
for(left=0;left<n;left++) for(right=left+1;right<n; right++) { current_sum=0; for(int i=left; i<right; i++) { current_sum+=sequence[i]; if(current_sum>max_sum) max_sum=current_sum; } }
穷举法改进: 当left确定时,子列和随着right的后移在上一次的计算结果上进行运算,所以可以在每次的begin开始时将当前子列和归零。
for(int left=0; left<n; i++) { int current_sum=0; for(int right=left; right<n; right++){ current_sum+=sequence[right]; if(current_sum>max_sum) max_sum=current_sum; } }
在线处理 : (本题不考虑和为负数的情况)当子列和小于0时,它对于最大子列和没有贡献(即该段子列肯定不在最大子列当中),可以将当前子列和归零,继续后面的寻找。
for(int i=0; i<n; i++) { current_sum+=sequence[i]; if(current_sum>max_sum) max_sum=current_sum; if(current_sum<0)//关键点 current_sum=0; }
比较
方法 | 复杂度 |
---|---|
1 | O(n^3) |
2 | O(n^2) |
3 | O(n) |
加强版
原题: 最大子列和2
问题分析
(1)考虑到全是负数和只有负数和0的情况:可以设置一个Max函数返回母序列的最大值。若最大值为0,则是只有负数和0(也可能全为0)的情况,最大子序列就是母序列中的第一个0;若最大值小于0,则是全是负数的情况,按照题意最大子列和设为0,并输出母序列的第一个值和最后一个值。
if(max<=0)
{
//全为负数
if(max<0){
max_sum=0;
begin=sequence[0];
end=sequence[n-1];}
int j=0;
//负数和0
if(max==0){
while(sequence[j]!=0){
j++;
}
max_sum=0;
begin=sequence[j];
end=sequence[j];
}
}
(2)解决输出最大子列的头和尾的问题: 可以在在线处理的方法上进行简单的修改即可。由之前说的在线处理方法可知,在子列和小于等于0的时候对于最大子列和是没有贡献的,所以我们可以在子列和小于0的时候记录下当前位置,则最大子列的开头位置就是该位置的后一个位置,结尾位置可以直接在记录最大子列和的时候同时记下。
for(int i=0; i<n; i++)
{
current_sum+=sequence[i];
if(current_sum<=0){
current_sum=0;
p=i+1;
}
if(current_sum>max_sum)
{
max_sum=current_sum;
end=sequence[i];
begin=sequence[p];
}
}
完整程序实现
1
#include<iostream>
using namespace std;
const int K=100000;
int subsequence1(int sequence[],int n){
int left,right;
int current_sum=0;
int max_sum=0;
for(left=0;left<n;left++)
for(right=left+1;right<n; right++)
{
current_sum=0;
for(int i=left; i<right; i++)
{
current_sum+=sequence[i];
if(current_sum>max_sum)
max_sum=current_sum;
}
}
return max_sum;
}
int subsequence2(int sequence[],int n){
int max_sum=0;
for(int i=0; i<n; i++){
int current_sum=0;
for(int j=i; j<n; j++){
current_sum+=sequence[j];
if(current_sum>max_sum)
max_sum=current_sum;
}
}
return max_sum;
}
int subsequence3(int sequence[],int n){
int current_sum=0;
int max_sum=0;
for(int i=0; i<n; i++)
{
current_sum+=sequence[i];
if(current_sum>max_sum)
max_sum=current_sum;
if(current_sum<0)
current_sum=0;
}
return max_sum;
}
int main(){
int sequence[K];
int N;
cin>>N;
for(int i=0; i<N; i++)
cin>>sequence[i];
cout<<subsequence2(sequence,N)<<endl;
return 0;
}
2加强版
#include<iostream>
using namespace std;
const int K=100000;
int Max(int sequence[],int n)//找出数组中的最大值
{
int max=sequence[0];
for(int i=0;i<n;i++)
if(sequence[i]>max)
max=sequence[i];
return max;
}
int subsequence(int sequence[],int n){
int current_sum=0;
int max_sum=0;
int begin;
int end;
int p=0;
int max=Max(sequence,n);
if(max<=0)
{
//全为负数
if(max<0){
max_sum=0;
begin=sequence[0];
end=sequence[n-1];}
int j=0;
//负数和0
if(max==0){
while(sequence[j]!=0){
j++;
}
max_sum=0;
begin=sequence[j];
end=sequence[j];
}
}
for(int i=0; i<n; i++)
{
current_sum+=sequence[i];
if(current_sum<0){
current_sum=0;
p=i+1;
}
if(current_sum>max_sum)
{
max_sum=current_sum;
end=sequence[i];
begin=sequence[p];
}
}
cout<<max_sum<<" "<<begin<<" "<<end;
}
int main(){
int sequence[K];
int N;
cin>>N;
for(int i=0; i<N; i++)
cin>>sequence[i];
subsequence(sequence,N);
return 0;
}
鸡汤
第一次写博客,希望可以坚持下去!