最大连续子序列求和详解

求解最大连续子序列的和以及最大连续子序列 求解最大连续子序列的和以及最大连续子序列——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>
MATLAB实战:Gardner定时同步算法实现与BER曲线优化指南 本文详细介绍了Gardner定时同步算法在MATLAB中的实现与优化方法,重点解析了算法原理、关键步骤实现及BER曲线绘制中的常见问题解决方案。通过优化参数设置和系统架构,提升数字通信系统的符号同步性能,为QPSK、QAM等调制系统提供实用参考。 阅读详情

相关推荐

[官方培训]22-UE资产优化 Epic 肖月 笔记

Nanite+Lumen目标:面向TA,美术,不影响视觉的前提下,优化运行和编辑效率引擎:UE5.1延迟管线平台:主流PC,Windows 10 with DX12。

Tcohneyn的博客 1576

最大连续子序列和(java)

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

jiaohanhan的博客 1万+

【算法实战】Keystone变换:从原理到MATLAB实现的距离走动校正

本文深入解析Keystone变换在雷达信号处理中的距离走动校正应用,从原理到MATLAB实现全面讲解。通过三种实现方法(DFT+IFFT、Sinc插值、Chirp-Z变换)的对比分析,结合实战案例展示如何有效解决高速目标导致的距离单元跨越问题,提升多普勒频谱聚焦质量。

weixin_29055699的博客 295

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

求一个整型数组中的最大连续子序列和,例如数组(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

手把手教你用Simulink+CANoe+Carsim搭建硬件在环仿真环境(避坑指南)

本文是一份详细的硬件在环仿真环境搭建指南,重点讲解如何将Simulink、CANoe和CarSim三大工具进行实战融合。内容涵盖软件版本兼容性、授权避坑、环境配置,并分步演示了从离线联合仿真到实现软实时同步的完整流程,旨在帮助汽车电子工程师高效构建稳定的HIL测试平台。

weixin_29092579的博客 406

ADS 使用教程(十八)Encrypting Designs using RFIP Encoder in ADS

在这一节,我们使用RFIP Encoder进行设计加密,这是一种保护知识产权和敏感设计数据的重要方法。RFIP Encoder提供了一种安全的方式来加密设计文件,确保只有授权人员能够访问和使用这些文件。

Dirge19的博客 1169

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

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

diaosangwan0363的博客 849

BMS | 从一串到几百串硬件架构简介

锂电池在生活中越来越多的方面扮演能源的角色,除了大家熟知的电动汽车行业,在一些消费类,工业类电子产品比如手机,电动自行车,电动工具中都有应用,追本溯源今天我们一起来学习下最基础的BMS架构。 1~4串架构 以S8241为代表的无通信/无固件/模拟器件 可实现过充保护、过放保护、过流/短路,参数由器件后缀代码决定;通信类手持设备供电系统;1~4节电池保护板架构 如图使用S-8241系列保护IC,一对充放电MOS管控制充放电的回路的切断和接通,系统供电来自于电芯电压,VM引脚用于检测过...

ningvay的博客 9918

【力扣】最大子数组和

给你一个整数数组 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

Unity3d实现的十字路口的模拟(一)

最近学习了Unity3d这个游戏引擎,感觉真的是非常的强大,正好赶上操作系统课程要做一个模拟信号量的模拟程序,于是打算做一个模拟十字路口的程序,大致的实现要实现的成果是:存在四种不同的汽车,包括一辆警车(不受交通信号灯的控制)随机产生在不同的路口,并且有不同的行动路线如:直走,左转,右转等,当然还有交通信号灯来控制车辆的有序运行。可以展示不同的视角来观察路口的情况(利用Q,W,E,R分别控制不同的

永远在身边的专栏 7489

微信小程序 - 最新详细实现调起手机摄像头拍摄身份证人像面和国徽面取景框功能,在拍照相机上增加身份证证件照的轮廓或自定义文字,支持替换扫描拍摄辅助线图片及文本,小程序实现拍照身份证时带取景轮廓框拍摄!

微信小程序,身份证,证件照,人像,证件照提示框模板,vue身份证拍照框,摄像机相机里有引导内容,取景框拍摄,微信小程序实现拍照界面自定义实现,自拍人相框拍摄,取景框,户口簿取景框,画布指定区域生成图片,微信小程序身份证正反面拍照如何加入辅助图片引导照片,身份证取景框拍摄,服务器,上传,正反面,调起手机摄像头:拍摄身份证的正反面,自定义身份证取景框,在相机上绘制“身份证轮廓“与提示文字,拍摄身份证时出现人像框怎么实现,在相机上增加图片和文字,微信小程序怎么给调起的相机加入自定义图片,小程序实现给相机上面

🏆 前端领域优质创作者 1万+

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

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

weixin_39654245的博客 322

1分钟了解LangChain是什么?

是一个基于大型语言模型(LLM)开发应用程序的框架, 它旨在简化语言模型应用的开发流程,特别是在构建对话系统和其他基于语言的AI解决方案时.目标是将复杂的语言模型技术转化为可通过简单API调用实现的功能,从而使开发者能够更加专注于创造性的解决方案设计。高效地解决了开发大语言模型应用的痛点问题。Langchain 最主要的特色是可以将 LLM 应用研发过程中的交互 Prompt、LLM 模型调用、语言模型与环境互动的自适应等方式融为一体。

gorgor在码农 2630

最大连续子序列

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

wxy33的博客 174

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

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

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

向小凯同学学习 3447

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

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

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

u012283461的博客 2527

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

最大连续子序列乘积

问题描述 给定一个整数序列(可能有正数,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、付费专栏及课程。

余额充值