最大连续子序列求和详解

求解最大连续子序列的和以及最大连续子序列 求解最大连续子序列的和以及最大连续子序列——java实现 阅读详情
原

最大连续子序列求和详解

<div class="article-info-box">
    <div class="article-bar-top d-flex">
                                            <span class="time">2012年11月27日 01:47:05</span>
        <div class="float-right">
            <span class="read-count">阅读数:25130</span>
                                        </div>
    </div>
</div>
<article>
    <div id="article_content" class="article_content clearfix csdn-tracking-statistics" data-pid="blog" data-mod="popu_307" data-dsm="post">
                <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/htmledit_views-0a60691e80.css">
        <div class="htmledit_views">

Maximum Continuous Subsequence Sum

最大连续子序列求和详解

1.        问题描述

输入一个整数序列(浮点数序列也适合本处讲的算法),求出其中连续子序列求和的最大值。

 

2.        算法分析

2.1.        算法一

2.1.1.       算法描述

遍历所有子序列并求和,比较得出其中的最大值。

2.1.2.       代码描述

1          public static int maxSubSumCubic(int[] array) {

2                 int maxSum = 0;  //最大子序列求和

3                 //start表示要求和的子序列的开始索引,end表示结束索引

4                 for(int start = 0; start < array.length; start++) {

5                        for(int end = start; end < array.length; end++) {

6                               int thisSum = 0;   //当前子序列求和

7                               //求出array[start]~array[end]子序列的和

8                               for(int index = start; index <= end; index++) {

9                                      thisSum += array[index];

10                           }

11                           //判断是否大于之前得到的最大子序列求和

12                           if(thisSum > maxSum) {

13                                  maxSum = thisSum;

14                           }

15                    }

16             }

17             return maxSum;

18      }

2.1.3.       算法分析

设输入序列长度为N,算法一有三个循环嵌套,第4行的循环长度为N。第5行的循环长度为N-start+1,因为我们考虑的是最差性能,所以可取为最大的N。第8行的循环长度是end-start+1,同理可取为N。所以可得算法的运行时间是O(N*N*N)=O(N^3 ),即算法的运行时间是以输入长度的立方增长的。可想而知,一旦输入长度变大,算法的运行效率将慢得无法接受,这也从反面说明了算法设计的重要性。

 

2.2.        算法二

2.2.1.       算法描述

算法设计的一个重要原则就是“不要重复做事”。在算法一中,对array[start]~array[end]子序列求和,可以由上一次求和array[start]~array[end-1]的结果加上array[end]得到,而不用从头开始计算。

2.2.2.       代码描述

1          public static int maxSubSumQuadratic(int[] array) {

2                 int maxSum = 0;  //最大子序列求和

3                 //start表示要求和的子序列的开始索引,end表示结束索引

4                 for(int start = 0; start < array.length; start++) {

5                        int thisSum = 0;   //当前子序列求和

6                        for(int end = start; end < array.length; end++) {                            

7                   //已求得的array[start]~array[end-1]子序列的和加上array[end]

8                               //得到array[start]~array[end]子序列的和

9                               thisSum += array[end];                         

10                           //判断是否大于之前得到的最大子序列求和

11                           if(thisSum > maxSum) {

12                                  maxSum = thisSum;

13                           }

14                    }

15             }

16             return maxSum;

17      }

2.2.3.       算法分析

算法二比算法一少了一个循环,同之前的分析一样,容易得到该算法的运行时间为O(N^2 ),算法的运行时间是以输入长度的立方增长的。

 

2.3.        算法三

2.3.1.       算法描述

考虑把输入序列从中间分成两半,那么最大和子序列的位置存在三种情况:1、最大和子序列完全在输入序列的左半部分;2、最大和子序列完全在输入序列的右半部分;3、最大和子序列跨越左右两部分。

 

所以,为了得到输入序列的最大子序列和,我们可以分别求出左半部分的最大子序列和、右半部分的最大子序列和、以及跨越左右两部分的最大子序列和,比较三者得出最大者就是要求的。

求左半部分的最大子序列和,可把左半部分作为新的输入序列通过该算法递归求出。右半部分的最大子序列和也同理。

接下来就是求解跨越左右两部分的最大子序列和,也就是求出左半部分中包含最右边元素(如图中的12)的子序列的最大和,和右半部分中包含最左边(如图中的6)的子序列的最大和,将两者相加即为跨越左右两个部分的最大子序列和。

另外还有一个需要说明的就是,对于有奇数个元素的数组,那么左右两半部分并不是平分的,但这其实不是问题。上面的算法并不要求是两半部分,分成任意两部分都可以。

2.3.2.       代码描述

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

2                 //递归的基准情况:待处理序列只有一个元素

3                 if(left == right) {

4                        //空集也算是子序列,空集和为0,所以最大子序列和最小为0

5                        if(array[left] > 0)

6                               return array[left];

7                        else

8                               return 0;

9                 }

10            

11             //递归求出左半部分和右半部分的最大子序列和

12             int center = (left + right) / 2;

13             int maxLeftSum = maxSubSumRec(array, left, center);

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

15            

16             //求出左半部分中包含最右边元素的子序列的最大和             

17             int maxLeftBorderSum = 0, leftBorderSum = 0;

18             for(int i = center; i >= left; i–) {

19                    leftBorderSum += array[i];

20                    if(leftBorderSum > maxLeftBorderSum) {

21                           maxLeftBorderSum = leftBorderSum;

22                    }

23             }

24            

25             //求出右半部分中包含最左边元素的子序列的最大和             

26             int maxRightBorderSum = 0, rightBorderSum = 0;

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

28                    rightBorderSum += array[i];

29                    if(rightBorderSum > maxRightBorderSum) {

30                           maxRightBorderSum = rightBorderSum;

31                    }

32             }

33            

34             //跨越两个部分的最大子序列和

35             int maxLeftRightSum = maxLeftBorderSum + maxRightBorderSum;

36            

37             //maxLeftSum、maxRightSum、maxLeftRightSum中的最大值即为最大子序列和

38             int maxSubSum = 0;

39             maxSubSum = maxLeftSum > maxRightSum ? maxLeftSum: maxRightSum;

40             maxSubSum = maxSubSum > maxLeftRightSum ? maxSubSum: maxLeftRightSum;

41            

42             return maxSubSum;

43      }

2.3.3.       算法分析

设T(N)表示输入序列长度为N时的运行时间,若N=1,即只有一个元素,那么left==right,所以有T(1)=1。对于N>1,程序需运行两个递归调用和两个for循环。其中每个递归调用的运行时间相当于输入长度为N/2时算法的运行时间T(N/2),两个递归则为2T(N/2)。每个for循环的运行次数为N/2,循环体中的语句运行时间是常数,所以两个for循环的运行时间为O(N/2*2)=O(N)。所以对于N>1,有T(N)=2T(N/2)+O(N),为了方便,可用N代替O(N),数量级不变,所以T(N)=2T(N/2)+N。在Weiss的《数据结构与算法分析Java语言描述(第二版)》中,作者通过观察的方式得出T(N)=N*(K+1),其中N=2^k ,所以有T(N)=N*(k +1)=NlogN +N=O(N )。

这里笔者自己尝试推导出这个结果,如有疏误或更好的方法,请不吝指教。同样,假设N为2的K次方,如果不是2的K次方,直接推导可能会比较复杂。当然我们可以这么理解,如果N不是2的K次方,可以通过在输入序列开头加入n个0,使N=N+n变成2的K次方。因为增加了输入的长度,所以运行时间比原本的要长,因为算法分析是最差时的性能,所以能用变长了的运行时间来代替原来的运行时间。所以问题同样转化成N为2的K次方时,T(N)的表示式怎么求。好了,废话不多说,直接推导。

由T(N)=2T(N/2)+N两边同除以N,得

(T(N))/N=(T(N/2))/(N/2)+1   =>  (T(N))/N-(T(N/2))/(N/2)=1

令F(N)=(T(N))/N ,则有

F(N)-F(N/2)=1

往下递推有

F(N/2)-F(N/4)=1

    …

    F(2) - F(1)=1

以上K(=logN )个式子相加可得

F(N)-F(1)=1+…+1=logN

即

T(N)/N-T(1)/1=logN

可得

T(N)=N logN+N=O(N logN)

由以上推理过程可得该算法的运行时间为

T(N)=O(N logN) 

2.4.        算法四

2.4.1.       算法描述

设输入序列为A,长度为N,从a0开始求和并记录最大值,如a(0),a(0)+a(1),a(0)+a(1)+a(2)…,直到开始出现求和小于0则停止。设加到a(i)时开始小于0,即有a(0),a(0)+a(1),…,a(0)+…+a(p-1)都大于0,而a(0)+a(1)+…+a(p)<0。此时,可从a(p+1)重新开始求和并记录最大值。为什么可以这么做呢?我们把从a(1)到a(p)之间开始的子序列分为两种情形(设子序列的开始索引为start,结束索引为end):

1、end<=p,a(start)+…+a(end)=a(0)+…+a(start)+…a(end) –[a(0)+…+a(start-1)]。由前面知,对于start-1<p,有a(0)+…+a(start-1)>0,所以可得到a(0)+…+a(start)+…a(end)> a(start)+…+a(end)。又由于a(0)+…+a(start)+…a(end)已经考虑过了,所以比其小的子序列无需考虑。

2、end>p,因为1<=start<=p,有a(0)+…+a(start-1)>0而a(0)+…+a(start)+…a(p)<0,所以有a(start)+…a(p)= a(0)+…+a(start)+…a(p)-[ a(0)+…+a(start-1)]<0。对于end>p,有a(start)+…+a(p)+…+a(end)<a(p+1)+…a(end)。

综上所述,只需要从a(p+1)开始重新求和,重复以上步骤即可得到最大子序列求和。

2.4.2.       代码描述

1          public static int maxSubSumLinear(int[] array) {

2                 int maxSum = 0, thisSum = 0;

3                 for(int j = 0; j < array.length; j++) {

4                        thisSum += array[j];

5                        if (thisSum < 0) {

6                               thisSum = 0;

7                        }

8                        else if(thisSum > maxSum) {

9                               maxSum = thisSum;

10                    }

11             }

12             return maxSum;

13      }

2.4.3.       算法分析

算法四只有一个for循环,且循环里面语句的执行时间为常量,所以T(N)=O(N)。可见该算法的运行时间是线性增长的,比前三个算法的性能要好。另外一个优点就在于该算法每次就需要使用一个输入值array[j],所以如果是在硬盘或者网络传输的环境下,我们可以实现串行读取,减少内存占用。

 

 

References:

《数据结构与算法分析Java语言描述(第2版),Mark Allen Weiss

        </div>
            </div>
        </article>

    <div class="article-bar-bottom">
                    <div class="tags-box artic-tag-box">
        <span class="label">文章标签:</span>
                    <a class="tag-link" href="http://so.youkuaiyun.com/so/search/s.do?q=java&amp;t=blog" target="_blank">java                     </a><a class="tag-link" href="http://so.youkuaiyun.com/so/search/s.do?q=Java&amp;t=blog" target="_blank">Java                     </a><a class="tag-link" href="http://so.youkuaiyun.com/so/search/s.do?q=JAVA&amp;t=blog" target="_blank">JAVA                     </a><a class="tag-link" href="http://so.youkuaiyun.com/so/search/s.do?q=数据结构&amp;t=blog" target="_blank">数据结构                     </a><a class="tag-link" href="http://so.youkuaiyun.com/so/search/s.do?q=最大子序列求和&amp;t=blog" target="_blank">最大子序列求和                       </a><a class="tag-link" href="http://so.youkuaiyun.com/so/search/s.do?q=最大连续子序列求和&amp;t=blog" target="_blank">最大连续子序列求和                       </a><a class="tag-link" href="http://so.youkuaiyun.com/so/search/s.do?q=算法详解&amp;t=blog" target="_blank">算法详解                     </a>
    </div>
                    <div class="tags-box">
        <span class =“label”>个人分类:</ span> 
                    <a class =“tag-link”href =“https://blog.youkuaiyun.com/superchanon/article/category/1286629”target =“_ blank” > Java </a> <a class="tag-link" href="https://blog.youkuaiyun.com/superchanon/article/category/1290216" target="_blank">数据结构和算法</a> 
    </ div> 
                </ div>     <! - !empty($ pre_next_article [0]) - >        </ div>
离线迁移 Conda 环境到 Windows 服务器:用 conda-pack 摆脱硬路径限制 在进行深度学习算法的环境部署时,由于生产服务器被彻底隔离外网,只能把conda中env文件夹中的虚拟环境文件夹从开发机直接拷到Windows 服务器,但在运行labelimg等工具时可能报错,因此用conda-pack来解决。 阅读详情

相关推荐

T分布和T检验的理解,Python代码实现T检验的计算

每天学习一点,每天进步一点。 声明:本人所有的原创,都是自己在学习过程中的记录点滴,不一定都是对的,肯定也会有一些错误的想法。所以大家看一看就好,不可尽信。当然也欢迎指出。 T分布 定义,有来自标准正态分布的样本X ~ N(0,1),和来自卡方n分布的Y ~ X2(n), 那么有 Z= X/√(Y/n) 成为符合自由度为n的T分布 我们用Python代码画一下他的图形 # 给一个自由度,返回这个自由度的卡方分布 X²(n) def product(n): n = np.ceil(n).astype

PY_smallH的博客 8485

最大连续子序列和(java)

最大连续子序列是算法中经典的一个问题。作为总结,今天就从最简单的暴力求解,写道目前能达到最好的线性时间复杂度的算法。 问题描述:找出一个整型数组中的最大连续子序列的和 测试用例:int[] a = { 1, -3, 7, 8, -4, 12, -10, 6 }; 输出:23 //即最大连续子序列和是 7 + 8 - 4+ 12 = 231、O(n^3)的暴力求

jiaohanhan的博客 1万+

PCB布局布线要求及多层电路板叠加原则

例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。提示:以下是本篇文章正文内容,下面案例可供参考本文主要针对PCB布局布线中的要点进行了总结,并对多层电路板的叠加原则进行了解释。

Ka_wyb的博客 2939

求一个整型数组中的最大连续子序列和

求一个整型数组中的最大连续子序列和,例如数组(3,2,-1,4,-3)中和最大的连续子序列为(2,-1,4),其和为5。 Java代码如下: public class Main { public static void main(String args[]) { int[] arr = { -3, 2, -1, 4, -3 }; System.out.println(maxSum(a

csulfy的博客 3726

Xilinx_JESD204B

Xilinx_JESD204B_AXI配置 说明:通过FPGA的高速数据接口JESD204B对AD9625进行高速采集。 环境:Vivado2018.3。 IP核:JESD204(7.2)。 参考手册:pg066_jesd204 v7.2。 资料以及IP_licence:JESD204B AXI协议资料:AXI 文章目录JESD204B概述JESD204B接口术语JESD204B 层JESD204B_AXI介绍AXI介绍JESD204B__AXI_Lite接口AXI-Lite接口介绍AXI-Lite接口信号

Crazzy_M的博客 1万+

c\c++: Identifiers, modifier, qualifier, specifier, decorator; systemtap

文章目录参考英语含义在c、C++ 参考 c++ 标准 https://blog.youkuaiyun.com/tyronne/article/details/44016621 英语含义 modifier word or phrase that modifies (modify 2) another word or phrase 修饰语. qualifier (grammar) word, esp an adjective or adverb, that qualifies another word 修饰词; (尤指)形

mzhan017的博客 2431

K:求取数组中最大连续子序列和的四个算法

相关介绍:  求取数组中最大连续子序列和问题,是一个较为“古老”的一个问题。该问题的描述为,给定一个整型数组(当然浮点型也是可以的啦),求取其下标连续的子序列,且其和为该数组的所有子序列和中值为最大的。例如数组A={1, 3, -2, 4, -5},则最大连续子序列和为6,即1+3+(-2)+ 4 = 6。解决该问题的算法有四种,根据其时间复杂度的高低,下面分别为这四种算法做介绍。 第一...

diaosangwan0363的博客 849

NXOpenC#-通用NX对象操作Tag,Handle,TaggedObject介绍

NXOpenC#-通用NX对象操作Tag,Handle,TaggedObject介绍

阿飞2018 1186

【力扣】最大子数组和

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。子数组 是数组中的一个连续部分。示例 1:输入:nums = [-2,1,-3,4,-1,2,1,-5,4] 输出:6 解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。 示例 2:输入:nums = [1] 输出:1 示例 3:输入:nums = [5,4,-1,7,8] 输出:23 提示:1 ...

cxh21627的博客 579

综述性论文别再堆砌文献!用GPT-5.1 Thinking轻松攻克四大关键难点,真正实现高效高质撰写(附AI提示词)

逻辑构建上以往都是先梳理一篇文献的领域研究脉络,明确其发展阶段、核心议题等,再搭建初步的大纲,借助思维导图或者别的方式将筛选后的文献观点按主题归类到对应章节,理清楚每个章节间的递进或并列关系,最后再逐个章节进行补充过渡表述,那么做的目的其实就是摆脱文献堆砌问题。人工做法往往是对比不同文献的研究方法、数据来源与核心结论,再清晰标注每类成果的优缺点,找到文献中存在的争议焦点,找到之后再梳理争议产生的核心原因,最后在基于现有研究,推出还未被探索的研究方向,从而提炼出创新切入点。2)文献之间的相同点与不同点;

智能AI让学术科研更容易 174

要理解成本中心与利润中心的根本区别与适用场景,需从 “责任范围、考核核心、管理目标” 三个核心维度切入,同时明确二者在企业管理体系中的联动关系

摘要: 成本中心与利润核心区别在于责任范围、考核目标和管理权限。成本中心仅对成本负责(如生产、行政部门),考核成本控制能力;利润中心需同时管控成本与收入(如独立产品线、区域分公司),以利润为核心指标。选择标准取决于单元是否拥有收入决策权:无收入权的支持/执行部门设为成本中心,能独立经营、核算盈亏的单元设为利润中心。二者协同运作,成本中心为利润中心提供基础支持,利润中心的需求动态影响成本中心资源配置,共同实现企业整体目标。划分本质是确保考核指标与责任范围匹配,避免管理失效。

金牌架构师 657

最大子序列求和_最大连续子序列求和详解

Maximum Continuous Subsequence Sum最大连续子序列求和详解1. 问题描述输入一个整数序列(浮点数序列也适合本处讲的算法),求出其中连续子序列求和的最大值。2. 算法分析2.1. 算法一2.1.1. 算法描述遍历所有子序列并求和,比较得出其中的最大值。2.1.2. 代码描述1 publ...

weixin_39654245的博客 322

1、动作捕捉技术:概述与历史

本博文全面介绍了动作捕捉技术的概念、历史演变、类型分类以及完整的工作流程。从早期的连续摄影技术到现代数字动作捕捉系统,文章深入探讨了光学、磁性和机械动作捕捉系统的优缺点及适用场景,并详细解析了动作捕捉数据的生成原理与数学基础。此外,还涵盖了特殊部位如手部、面部和木偶的动作捕捉方法,并讨论了动作捕捉在动画制作、虚拟现实、医疗康复等领域的广泛应用与发展前景。

apple5的专栏 221

最大连续子序列

Description 给定K个整数的序列{ N1, N2, ..., NK },其任意连续子序列可表示为{ Ni, Ni+1, ..., Nj },其中 1 例如给定序列{ -2, 11, -4, 13, -5, -2 },其最大连续子序列为{ 11, -4, 13 },最大和 为20。 在今年的数据结构考卷中,要求编写程序得到最大和,现在增加一个要求,即还需要输出该

wxy33的博客 174

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

最大连续子序列求和(算法)亲测完整C语言代码

最大连续子序列求和(算法)亲测完整C语言代码 虽然楼主是一个Java程序员,但是最近在学习的时候,遇到一个问题:最大连续子序列求和。 当时这个问题是个很好的问题,如果理解透彻了,就会很easy。实现的时间复杂度,也很多,非常适合学习研究。 一、引入讲解文章 在知乎上有一篇文章讲解了一个理解思路是非常不错的。 建议用笔和纸写一写画一画,光靠看肯定会很懵。 最大连续子序列求和的一种理解思路 二、楼...

向小凯同学学习 3447

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

最大连续子序列求和的5种解法

题目链接 【题目描述】洛谷1115最大连续子序列求和 给出一段序列,选出其中连续且非空的一段使得这段和最大。 【输入格式】 第1行是一个正整数N(N≤200000),表示了序列的长度。 第2行包含N个绝对值不大于10000的整数A[i],描述了这段序列。 【输出格式】 输出仅包括1个整数,为最大的子段和是多少。子段的最小长度为1。 解题方案: 暴力枚举O(n3) 枚举——优化O(n2) 枚举...

u012283461的博客 2527

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

最大连续子序列乘积

问题描述 给定一个整数序列(可能有正数,0和负数),求它的一个最大连续子序列乘积。比如给定数组a={3, -4, -5, 6, -2},则最大连续子序列乘积为720,即3*(-4)*(-5)*6=720。 分析 求最大连续子序列乘积与最大连续子序列和问题有所不同,因为其中有正有负还有可能有0。 假设数组为a[],直接利用动归来求解,考虑到可能存在负数的情况,我们用Max[i]来

__七把刀__ 7996

连续子序列求和的最大值

输入一个整数序列(浮点数序列也适合本处讲的算法),求出其中连续子序列求和的最大值。 public static int maxLength(int []arr,int k) { if(arr==null||arr.length==0) { return 0; } HashMap<Integer,Integer>map=new HashMap<Integ...

wysw1998的博客 823

最大连续子序列求和问题

最大连续子序列求和问题如下: 给定一个序列:A1,A2,A3......An,求i,j(1&lt;=i&lt;=j&lt;=n),使得Ai+.....+Aj最大,输出这个最大值的和。 例: 输入 -2 11 -4 13 -5 -2  显而易见11+(-4)+13=20为最大值,因此此时的最大值为20。 采用暴力法复杂度为O(),对于较大的序列来说,显然是无法承受的。 采用动态规划的方法...

weixin_43123900的博客 6595
上一篇: git 分支管理 推送本地分支到远程分支
下一篇: 中缀表达式转换成后缀表达式:
FLE123
博客等级 码龄10年 7粉丝 9原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值