最大子序列和问题的求解

怎么求出一个数组最大的连续累加之和呢?方法有很多,我们目前只讲一个比较不错的方法,该方法使用了分治递归的思想。

我们假设下面是我们需要计算的数组,其中A是游标,我可以知道游标将数组分成了两段,最大值有可能出现在前半段也有可能出现在后半段,还有一种情况是跨越A(中间)相加的一段。

[1,-3,5,7 A,9,-8,6,2]

跨越A相加的部分我们可以这样计算:


int maxLeftBorderSum =0;

int leftBorderSum =0;

for (int i = center;i >= left;i--){

    leftBorderSum += array[i];

    if (leftBorderSum>maxLeftBorderSum){

          maxLeftBorderSum = leftBorderSum;

    }

}

int maxRightBorderSum =0;

int rightBoederSum =0;

for (int i = center +1;i <= right;i++){

    rightBoederSum += array[i];

    if (rightBoederSum>maxRightBorderSum){

          maxRightBorderSum = rightBoederSum;

    }

}

以中间为起点向两边相加,然后将左右两边最大和相加:maxLeftBorderSum+maxRightBorderSum,即可得跨越A相加最大的。

前后端最大值可以通过递归求得:


int center = (left + right)/2;

int maxLeftSum =maxSumRec(array,left,center);

int maxRightSum =maxSumRec(array,center+1,right);

最后我们分析一下这个递归方法的基准方法:


if (left == right){

if (array[left]>0){
        return array[left];
    }else {
        return 0;
    }
}

因此完整的程序是:


public static void main(String[] args)throws Exception {

int[] array = {1,-5,4,6,-7,3,2,-5,9};

    System.out.println("结果:"+maxSumRec(array,0,array.length-1));

}

public static int maxSumRec(int[] array,int left,int right){

if (left == right){

if (array[left]>0){

return array[left];

        }else {

return 0;

        }

}

int center = (left + right)/2;

    int maxLeftSum =maxSumRec(array,left,center);

    int maxRightSum =maxSumRec(array,center+1,right);

    int maxLeftBorderSum =0;

    int leftBorderSum =0;

    for (int i = center;i >= left;i--){

leftBorderSum += array[i];

        if (leftBorderSum>maxLeftBorderSum){

maxLeftBorderSum = leftBorderSum;

        }

}

int maxRightBorderSum =0;

    int rightBoederSum =0;

    for (int i = center +1;i <= right;i++){

          rightBoederSum += array[i];

        if (rightBoederSum>maxRightBorderSum){
                maxRightBorderSum = rightBoederSum;
        }

}

return     max(maxLeftSum,maxRightSum,maxLeftBorderSum+maxRightBorderSum);
}

public static int max(int v1,int v2,int v3){
    if (v1>v2){
        return v1>v3?v1:v3;
    }else {
        return v2>v3?v2:v3;
    }
}

最后返回三者的最大值即可求得。

这种算法算是效率比较高的,但是根据合成效益法则可知,这个算法仍然有重复计算的部分。
下面说的这种算是则不会出现这种情况,只会对数组进行一次扫描。

public static void main(String[] args) throws Exception {
        int[] array = {1,-5,4,6,-7,3,2,-5,9};
        System.out.println("结果:"+maxSubSum(array));

    }

    public static int maxSubSum(int array[]){
        int thisSum = 0;
        int maxSum = 0;
        for (int i = 0;i<array.length;i++){
            thisSum += array[i];
            if (thisSum>maxSum){
                maxSum = thisSum;
            } else if (thisSum<0){
                thisSum = 0;
            }
        }
        return maxSum;
    }

这种算法是仅需要常量空间并以线性时间运行的联机算法。

根据原作 https://pan.quark.cn/s/459657bcfd45 的源码改编 Classic-ML-Methods-Algo 引言 建立这个项目,是为了梳理总结传统机器学习(Machine Learning)方法(methods)或者算法(algo),各位同仁相互学习交流. 现在的深度学习本质上来自于传统的神经网络模型,很大程度上是传统机器学习的延续,同时也在不少时候需要结合传统方法来实现. 任何机器学习方法基本的流程结构都是通用的;使用的评价方法也基本通用;使用的一些数学知识也是通用的. 本文在梳理传统机器学习方法算法的同时也会顺便补充这些流程,数学上的知识以供参考. 机器学习 机器学习是人工智能(Artificial Intelligence)的一个分支,也是实现人工智能最重要的手段.区别于传统的基于规则(rule-based)的算法,机器学习可以从数据中获取知识,从而实现规定的任务[Ian Goodfellow and Yoshua Bengio and Aaron Courville的Deep Learning].这些知识可以分为四种: 总结(summarization) 预测(prediction) 估计(estimation) 假想验证(hypothesis testing) 机器学习主要关心的是预测[Varian在Big Data : New Tricks for Econometrics],预测的可以是连续性的输出变量,分类,聚类或者物品之间的有趣关联. 机器学习分类 根据数据配置(setting,是否有标签,可以是连续的也可以是离散的)任务目标,我们可以将机器学习方法分为四种: 无监督(unsupervised) 训练数据没有给定...
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值