码迷,mamicode.com
首页 > 编程语言 > 详细

经典算法问题 - 最大连续子数列和

时间:2019-08-14 12:48:50      阅读:99      评论:0      收藏:0      [点我收藏+]

标签:max   http   strong   连续   例子   nbsp   分组   mem   dia   

维基百科:在计算机科学中,最大子数列问题的目标是在数列的一维方向找到一个连续的子数列,使该子数列的和最大。例如,对一个数列 −2, 1, −3, 4, −1, 2, 1, −5, 4,其连续子数列中和最大的是 4, −1, 2, 1, 其和为6。

时间复杂度:O(N^3)

最粗鲁的做法就是直接三重循环,起点i,终点j,k是从i到j

代码如下:

#include <bits/stdc++.h>

using namespace std;
                      
int main()
{
    int n;
    cin>>n;
    int a[n];
    for(int i=0;i<n;i++){
        cin>>a[i];
    }
    int ans=a[0];
     for(int i=0;i<n;i++){
         for(int j=0;j<n;j++){
             int s=0;
             for(int k=i;k<=j;k++){
              s+=a[k];     
             }ans=max(ans,s);
         }
     }cout<<ans;
    return 0;
}

时间复杂度:O(N^2)

将上述代码稍微优化一下(空间换时间)

#include <bits/stdc++.h>

using namespace std;
                      
int main()
{
    int n;
    cin>>n;
    int a[n],sum[n];//sum[i]表示从a[0]+a[1]+.....+a[i]; 
                        //sum[j]表示从a[0]+a[1]+.....+a[i]+....+a[j];
    memset(sum,0,sizeof(sum));
    for(int i=0;i<n;i++){
        cin>>a[i];
    }
    sum[0]=a[0];
    for(int i=1;i<n;i++){
        sum[i]+=sum[i-1]+a[i];
    }
    int ans=a[0];
     for(int i=1;i<n;i++){
         for(int j=i;j<n;j++){
             int s=sum[j]-sum[i-1];//sum[j]-sum[i-1]表示a[i]+....+a[j] 
            ans=max(ans,s); 
         }ans=max(ans,sum[n-1]);//因为s是sum[j]-sum[i-1]出来的所以至少减去了一个sum[0],
                                 //所以还得比较一次全部相加的结果 
     }cout<<ans;
    return 0;
}

时间复杂度:O(N)

 

Kadane算法[编辑]

 

Kadane算法扫描一次整个数列的所有数值,在每一个扫描点计算以该点数值为结束点的子数列的最大和(正数和)。该子数列由两部分组成:以前一个位置为结束点的最大子数列、该位置的数值。因为该算法用到了“最佳子结构”(以每个位置为终点的最大子数列都是基于其前一位置的最大子数列计算得出),该算法可看成动态规划的一个例子。

算法可用如下Python代码实现:

def max_subarray(A):
    max_ending_here = max_so_far = A[0]
    for x in A[1:]:
        max_ending_here = max(x, max_ending_here + x)
        max_so_far = max(max_so_far, max_ending_here)
    return max_so_far

常用的c++代码:

#include <bits/stdc++.h>

using namespace std;
                      
int main()
{
    int n;
    cin>>n;
    int a[n],dp[n];//dp[i]:截至到第i项的最大和 
    for(int i=0;i<n;i++){
        cin>>a[i];
    }    dp[0]=a[0];
    int ans=a[0]; 
    for(int i=1;i<n;i++){
        dp[i]=max(dp[i-1]+a[i],a[i]);//如果a[i]>dp[i-1]+a[i],
                                    //说明现在以a[i]作为新的起点累加的结果更大 
        ans=max(ans,dp[i]);            //注意最大的不一定是dp[n-1] 
    }
    cout<<ans;
    return 0;
}

 

技术图片
#include <bits/stdc++.h>

using namespace std;
                      
int main()
{
    int n;
    cin>>n;
    int a[n]; 
    for(int i=0;i<n;i++){
        cin>>a[i];
    }    
    int ans=a[0]; 
    for(int i=1;i<n;i++){
        a[i]=max(a[i-1]+a[i],a[i]);
        ans=max(ans,a[i]); 
    }
    cout<<ans;
    return 0;
}
不开辟dp数组

 

贪心:

#include <bits/stdc++.h>

using namespace std;
                      
int main()
{
    int n;
    cin>>n;
    int a[n]; 
    for(int i=0;i<n;i++){
        cin>>a[i];
    }
    int s=0,ans=a[0];    
    for(int i=0;i<n;i++){
    s+=a[i];
    ans=max(s,ans);
    if(s<0){
    s=0;    
    }
    
    }
    cout<<ans;
    return 0;
}

 

  

 

经典算法问题 - 最大连续子数列和

标签:max   http   strong   连续   例子   nbsp   分组   mem   dia   

原文地址:https://www.cnblogs.com/cstdio1/p/11350983.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!