最大子段和 or 最大子序和

老生常谈序列和串的区别

最长公共子序列和最长公共子串区别

最长公共子串(Longest Common Substring)与最长公共子序列(Longest Common Subsequence)的区别:

子串要求在原字符串中是连续的,而子序列则只需保持相对顺序一致,并不要求连续。

子串和子段,都要求连续

求最大子段(子序)和

意思就是,给定一个整数数组nums[],找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

输入: [-2,1,-3,4,-1,2,1,-5,4]

输出: 6

解释: 连续子数组[4,-1,2,1]的和最大,为6。

设有这样的一个数组:

{-2,-1,3,5,10,-2-,1,2,5,-2}

我们可以思考一下,最大的连续元素和,他们的不会让他们的和减小的负数

也就是说,当有前几个元素的和为负数的时候,后面的元素运算必定不会带上前面这个和为负数的子段

所以我们可以建立一个辅助数组MAX,存储他们的局部最优解

 

 

第一个开始,他自己本身就是自己的局部最优解,填入他自己

 

 下一个元素判断,他的前面的最优解是否为负数的话就上,自己本身,前面不是负数的话就把最优解自己填入

这里的第二个是-1 ,前面是-2 ,是负数,填入自己就行

 

 经过运算最后我们可以得到

 

 解下来在里面找到最大值即可,最大值就是他们的子段最大和

状态转移方程代码

 通过以上的分解后,我们可以得到这样一个状态转移方程

复制代码
function maxSubArray ( nums: number[] ) : number {
    for (let i = 1; i < nums. length; i++) {
        if(nums[i一1]>0){
            nums[i] = nums[i] + nums[i-1] ;
        }
    }
        return Math.max( ...nums ) ;
};
                
复制代码

返回序列信息

由于我们知道了最大sum值就是他的最长值

所以最大sum值就是得到子段的最后一个元素

我们从最后一个开始,往前遍历到负数的局部最优解,就是序列开始的前一个了

这样就能知道序列的开头和结尾了

代码

复制代码
# include<stdio.h>
 
int main(){
    int n;
    scanf("%d", &n);
    int a[n]={0};
    for(int i = 0;i<n;i++){
        scanf("%d", &a[i]);
    }
    int max = 0;  // 最大值
    int tem = 0;  // 段值
    for(int i=0;i<n;i++){
        if(tem>0)  // 前面一段值大于0
            tem+=a[i];
        else{  // 前面一段值小于0
            tem=a[i];  // 抛弃前面的段值,更新段值
        }
        if(tem>max){  // 更新最大值
            max=tem;
        }
    }
    printf("%d", max);
    return 0
}
复制代码

 

posted @   kuailest  阅读(46)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示