最大子序列之和问题

算法设计与分析——最大连续子序列之和问题 最大连续子序列之和问题是用来分析时间复杂度的很好的例子,这里简要分析和记述下整个过程。{3,4,-2,1,-5,-2,5}{-2,7,4,11,-2,-8,12,1}{-2,7,4,11,-2,-8,12,1,-3}{3,-2,7,4,11,-2,-8,12,1,-3}{-2,1,-2,3,-2,7,4,11,-2,-8,12,1,-3}{-2,1,-2,3,-2,7,4,-11,-2,-8,-1... 阅读详情
最大子序列之和问题
 
这个问题非常有趣,因为有很多中算法可以解决这个问题。而这些算法的执行效率也多种多样。
下面我们将看到四种算法,算法复杂度从指数一直过渡到线性复杂度。
充分体现了算法的优劣对执行效率的影响。
 
第一种
 

代码:

int maxSubSum1( const vector<int> & a ) {

    int maxSum = 0;

   

    for ( int i = 0; i < a.size(); i++ )

        for ( int j = 1; j < a.size(); j++ ) {

             int thisSum = 0;

             

             for ( int k = i; k <= j; k++ )

                 thisSum += a[k];

                

             if ( thisSum > maxSum )

                maxSum = thisSum;

        }

    return maxSum;

}

这个算法很简单,i表示子序列起始下标,j表示子序列结束下标,遍历子序列的开头和结束下标,计算子序列的和,然后判断最大子序列。很明显的看出算法复杂度是O( pow( n, 3 ) )

 

第二种算法
 
代码:

int maxSubSum2( const vector<int> & a ) {

     int maxSum = 0;

     

     for ( int i = 0; i < a.size(); i++ ) {

         int thisSum = 0;

         for ( int j = i; j <= a.size(); k++ ) {

             thisSum += a[k];

                 

             if ( thisSum > maxSum )

                maxSum = thisSum;

         }

     } 

     return maxSum;

}

 

与第一种很相似,省去了选结束下标的循环语句,算法复杂度是O( pow( n, 2 ) )

 

第三种
 
采用了递归的“分而治之”( divide-and-conquer  )的思想。

比如  4   -3   5   -2        -1   2   6   -2

          First                                               Second 

把序列分为两部分,那么最长子序列要么在First,要么在Second,要么就既在First又在Second。

第一中情况只要求First的最大子序列(递归调用),第二中情况只要求Second的最大子序列(还是递归调用)。对于第三种情况,只要找到包含First最后一个元素(在例子中是2)在First的最大子序列(例子中是 4,-3,5,-2)和包含Second起始元素(-1)在Second的最大子序列(-1,2,6)然后相加就行了。

这种算法的复杂度计算和计算斐波那契数列的复杂度相似,设 N 个数的执行次数是 T( N ) ,那么 T( N ) = 2*T( N/2 ) + O( N )  其中T( 1 ) = 1

O( N ) 可以看成 N ,那么可以观察得到 T( N ) = N * logN

 

int maxSumRec( const vector<int> & a, int left, int right ) {

    if ( left == right )

        if ( a[ left ] > 0 )

            return a[ left ];

        else

            return 0;

 

    int center = ( left + right ) / 2;

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

    int maxRightSum = maxSumRec( a, center, right );

 

    int maxLeftBorderSum = 0, leftBorderSum = 0;

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

        leftBorderSum += a[ j ];

        if ( leftBorderSum > maxLeftBorderSum )

            maxLeftBorderSum = leftBorderSum;

    }

 

    int maxRightBorderSum = 0, RightBorderSum = 0;

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

        RightBorderSum += a[ j ];

        if ( RightBorderSum > maxRightBorderSum )

            maxRightBorderSum = rightBorderSum;

    }

 

    return max3( maxLeftSum, maxRightSum, maxLeftSum + maxRightSum );       //   判断三个数最大值的函数

}

 

int maxSubSum3( const vector<int> & a ) {

    return maxSumRec( a, 0, a.size() - 1 );

}

 

第四种算法
 
代码:

int maxSubSum( vector<int> & a ) {

    int maxSum = 0, thisSum = 0;

    for ( int i = 0; i < a.size(); i++ ) {

        thisSum += a[i];

 

        if ( thisSum > maxSum )

            maxSum = thisSum;

        else if ( thisSum < 0 )

            thisSum = 0;

    }

    return maxSum;

}

非常短,而且一眼就看出算法复杂度是O( n )级别的。

我们用i表示子序列的起始下标,j 表示子序列的终止下标。

原理是,当我们得到一个子序列,如果子序列的第一个数是非正数,那么可以舍去,即i++

当一个子序列的前n个元素和为非正数时,是否也可以舍去呢?答案是可以的。

假设k 是i到j中任意一个下标。Sum( a, b ) 表示子序列第a个元素到第b个元素之和。由于加到第j个元素,子序列才开始为负数,所以Sum( i, k ) > 0,Sum( i, k ) + Sum( k, j ) = Sum( i, j ) ,所以Sum( k, j ) < Sum( i, j ) < 0

所以如果把 k到j的序列附加到j之后的序列上,只会使序列越来越小。所以i到j的序列都可以舍去。

 

这个算法的另外一个优势就是程序是一边读取一边处理数据,a[ i ] 的值不需要被记住,也就是说不需要把数列的一部分储存在内存中。如果数列是储存在磁盘上,或者是在网络中传播就可以按顺序处理。在任何时候,这个算法都可以根据收到的数据给出结果。有这种特点的算法叫做on-line 算法。

D2D与C2C高速互联技术对比:从封装到性能的全面解析 本文全面解析了Die-to-Die(D2D)与Chip-to-Chip(C2C)高速互联技术的差异,从封装形式、传输距离到性能指标进行深度对比。D2D技术在带宽、延迟和能效方面具有显著优势,适用于高性能计算和AI加速;而C2C技术则更适合车载电子系统等长距离传输场景。文章还探讨了UCIe标准化趋势,并提供了技术选型的实用建议。 阅读详情

相关推荐

Python手记-9:Python LXML库XPath的爬取晋江书目

1. lxml库 lxml是功能最丰富且易于使用的库,用于处理Python语言中的XML和HTML,还可实现WEB爬取,官文参考:https://lxml.de/,完整的PDF文档下载链接https://lxml.de/lxmldoc-4.5.0.pdf,但是阅读起来……em……怪自己不够聪明的样子。 Linux下安装lxml库:[root@chengyu ~]# pip3 instal...

成屿的专栏 4万+

最大子序列和问题

最大子序列和是指,给定一组序列,如 [1,-3,2,4,5],求子序列之和的最大值,对于该序列来说,最大子序列之和为 2 + 4 + 5 = 11。 这里的子序列要求是连续的,因此也可以称其为连续子数组最大和。 有几种不同的方法求解最大子序列和问题,但它们的复杂度相差甚远,尤其在面对大量数据的时候。实际上,效率最高的算法非常简短,只需要几行代码,最主要的是理解它的思想。 基本算法 这是一种比较容...

lslxy1021的博客 3万+

别再为EPI形变头疼了!FSL的topup+eddy实战保姆级教程(含AP/PA数据采集要点)

本文详细介绍了如何使用FSL的topup和eddy工具解决EPI形变问题,包括数据采集要点、参数设置和实战操作步骤。通过AP/PA双编码数据和精确的形变场估计,有效矫正MRI图像中的几何畸变,提升弥散数据质量。特别适合需要处理高场强MRI数据的研究人员和技术人员。

weixin_28725949的博客 399

最大子列和问题(四种方法 !!!终极版本)

最大子列和问题四种解法及复杂度分析

Bitdancing的专栏 7367

Wine7.22实战:如何在Ubuntu上完美运行通达信和微信(附字体配置技巧)

本文详细介绍了如何在Ubuntu系统上使用Wine7.22版本,完美运行通达信和微信这两款Windows专属软件。通过选择稳定的Wine7.22版本、利用现成的兼容容器,并重点解决了中文字体渲染的核心难题,提供了从环境搭建、字体配置到软件安装调优的一站式实战指南,帮助用户在Linux环境下无缝使用关键金融与通讯工具。

weixin_29280657的博客 549

Optisystem软件与Matlab软件的联合数据读取

目录 Matlab软件程序编写 Optisystem软件的连接与设置 数据读取结果 Matlab软件程序编写 利用Matlab软件按照下图编写程序,保存为getdata.m文件。 OutputPort1 =InputPort1; fileID=fopen('OSAdata.txt','wt'); fprintf(fileID,'%f\n',OutputPort1.Sampled.Signal); fclose(fileID); Optisystem软件的连接与设置 (以基于线性插值法

Vivian_Chen_的博客 4853

算法:最大子序列求和问题

最大子序列求和问题

weixin_44507219的博客 4725

SIPVicious实战指南:从零开始掌握VoIP渗透测试(Kali Linux环境)

本文为SIPVicious实战指南,详细介绍了在Kali Linux环境下进行VoIP渗透测试的完整流程。从环境准备与工具安装开始,逐步讲解如何使用svmap扫描SIP服务器、svwar枚举PBX分机号,以及svcrack进行密码安全测试,并整合svreport生成报告。旨在帮助安全从业者从零开始,系统掌握这套经典开源工具,在授权范围内有效评估VoIP系统的安全性。

weixin_29327977的博客 537

最大子列和问题的四种算法

算法1 三重循环,时间复杂度O() int MaxSubseqSum1(int a[], int n) { int ThisSum, MaxSum = 0; int i, j, k; // i是左端位置,j是右端位置 //* 三重循环 for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { ThisSum = 0; for

LeiMo_03的博客 1907

点云结构面智能识别与裂隙网络分析系统

点云结构面智能识别系统摘要 本系统采用深度学习与传统几何算法融合的方法,实现岩石结构面的智能识别与分析。系统包含7个核心模块:点云预处理、结构面识别、分组分割、参数计算、粗糙度分析、裂隙网络生成和可视化。技术路线结合PointNet++深度学习架构与RANSAC、区域生长等传统算法,通过预处理→深度学习识别→几何精修→参数计算→网络构建的流程实现高精度分析。预处理模块实现点云降噪、下采样和法向量估计,深度学习模块基于改进的PointNet++架构进行特征提取和分类。系统支持多种点云格式输入,提供完整的结构面

huanghm88的专栏 345

ISOLAR Autosar BSW 配置 之 Com

Autosar ISOLAR Bsw Configuration 之 Com

qq_42262743的博客 453

动态规划——最大子序列之和-数塔问题

package OJ; import java.util.*; import java.util.regex.Matcher; public class Bully { /* * 动态规划经典五题——基础 * 1.最大连续子序列之和 * 2.数塔问题 * */ public static void main(String[] args) {

lily0806的专栏 456

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

最大连续子序列之和问题

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34400525的博客 166

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

最大的子序列之和问题

最大的子序列之和问题 最大子序列和问题 问题描述:     输入一组整数,求出这组数字子序列和中最大值。也就是只要求出最大子序列的和,不必求出最大的那个序列。例如: 序列:-2 11 -4 13 -5 -2,则最大子序列和为20。 序列:-6 2 4 -7 5 3 2 -1 6 -9 10 -2,则最大子序列和为16。 算法一: //穷举法,复杂度O(n^3) long

Mr.Simple的专栏 1701

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

求最大子序列之和问题

问题描述                 给定一组整数序列,求出这组序列和中的最大值,不要求求出最大的子序列。                 例如:                              序列:-2 11 -4 13 -5 -2,则最大子序列和为20。                           序列:-6 2 4 -7 5 3 2 -1 6 -9

Heavy_Dream的博客 471

最大连续子序列之和的问题

/** *算法复杂度只有O(n)的线性算法 *如果子序列的和为负数,那么它就不可能是成为和最大的连续子序列的一部分 */ public static int maxSubsequenceSum(int[] a) {     int maxSum = 0;     int thisSum = 0;          for(int i=0,j=0; j     {

code to success 515

使用不同方法求解最大子序列之和问题

/* Solutions for the Maximum Subsequence Sum Problem 四种方法,时间复杂度依次递减:O(N^3)、O(N^2)、O(N log(N))、O(N) */ #include<vector> #include<algorithm> #define CATCH_CONFIG_MAIN #include"c...

ddq58011的博客 126

其他笔记 - 连续子序列之和为定值/最大最小的问题

连续子序列为定值问题 给定一个数组nums和定值k,求连续子序列之和为k的个数。 这个题,由于数组并不是排序号的递增整数数组,所以感觉用滑动窗口或者判断大小的方法来做不合适。 但是由于你最关注的是等于k的子序列数目,关心的是和而不是下标,所以可以考虑用一个字典来存储状态,结果res则累加。 sum为遍历到i时,从0到i的序列和。 判断条件: 当序列和等于k,也就是sum-k为0时,说明该连续子序列之和为k,符合条件,res+1,也可以再初始化的时候{0:1},这样避免每次都要判断一次再累加。 arr更新条件

参谋谋的博客 1190

(java)整数数组中求最大连续子序列之和,并且记录开始和结束位置

题意: 如题目所示,就是求一个数组中最大连续子序列之和并且记录开始和结束下标。 这是经典的一个动态规划问题,时间复杂度为O(N) public class TestMaxQueue { public static void main(String[] args) { // TODO Auto-generated method stub int[] num=new int[]{-2

飞行的码农 5467

最大连续子序列之和问题(O(n*n)

#include&lt;iostream&gt; #include&lt;stdlib.h&gt; using namespace std; int MaxSubsequenceSum(int a[],int length){ int MaxSum = 0; int ThisSum,SeqStart,SeqEnd; for (int i = 0; i &lt; length; i++) ...

一个正在路上的学生 469

最大上升子序列之和

题目 题目中已告诉最长上升子序列之和!=最大上升子序列之和 动态规划的比较重要的点 1. 拆分成子问题 2. 状态转移方程 (其实动态规划也可以理解为递归的逆过程) 根据这道题来实操一下 拆分成子问题 求的是n个数的最大上升子序列之和 则可以拆分成求n-1个数的最大上升子序列之和 以此类推 最后是先求1个数的最大上升子序列之和 //这里是做题自己想 (这里有没有一点递归的味道,1为返回条件) 从求当一个数时到求当两个数时的最大上升子序列之和 以此类推,最后由求当n-1时到当n时的最大上升子序列之和 //

Geek_J的博客 1007
上一篇: FLEX quick start XML数据处理
下一篇: PHP + SQL + FLEX 制作简单留言板
农夫三拳
博客等级 码龄18年 31粉丝 22原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值