问题描述

给定由 n 个整数(可能为负整数)组成的序列 a1、a2、……an,求该序列形如
的子段和的最大值。当所有整数均为负整数时定义其最大子段和为 0。依次定义,所求的最优值为

max{

例如:当(a1,a2,a3,a4,a5,a6)=(-2,11,-4,13,-5,-2)时,最大子段和为
=20。

三种算法求解

1、暴力算法

算法分析:

通过阅读了解问题后,可以初步尝试用最简单的方法解决问题,方便发现问题本质。最大子段和的结果很明显是通过:对数组排列组合得出子段和的个数,然后一一对比得出结果。

求子段和的个数需要两个循环:外循环是循环起点,内循环是循环终点。

求子段和对比结果需要一个循环。

三个for循环的时间复杂度是O(n3),然而在第二个for循环求处子段个数时就可以进行子段和比较了,省去最后一个for循环,使得算法时间复杂度为O(n2)。

算法实现:

算法伪代码:

2. 分治算法

算法分析:

可以从数组中间分开,结果要么在左边或右边,要么就在中间。结果在左边和右边的情况好办,那在中间的情况该如何分析呢?因为子段是连续的,所以结果只能从中心向两边扩,采用枚举法,左右走到尽头,结果相加就得到中间的最大解。所以该题采用分治算法的难度就可以解决了。

拆分子数组分别求得的最大子段和为sum1,sum2。时间复杂度为2T(N/2),从中心点向两边找最大的和,找到跨越的最大子段和的时间复杂度为O(n), 所以总体的时间复杂度为:T(n)=2T(n/2)+O(n) = O(nlogn)。

算法实现:

算法伪代码:

3. 动态规划

算法分析:

首先,该问题的解法符合动态规划的思想。

一、子问题重叠:无论问题规模怎么变化,最大子段和的子段都是在数组中。

二、原问题的最优解包含子问题的最优解:通过最简单的方法,我称之为暴力带值。列出小问题规模的结果,通过矩阵a[i]存入数值:

a[i] -2 11 -4 13 -5 -2

在分治算法中,需要枚举n个数组,那如果从a[0]开始枚举,得到一段子段和是负数,那还需要用到该子段吗?显然不需要,直接从当前元素重新开始。

假定子段终点为a[j],那么之前的和必定为正且最大,设置b[i]数组记录a[j]结尾的全部子段的和,所以当b[j]>0时,b[j]=b[j-1]+a[j],否则b[j]=a[j],由此得到b[j]的动态规划递归式:

b[j]=max{b[j-1]+a[j],a[j]}, 1≤j≤n

b -2 11 7 20 15 13
sum 0 11 7 20 20 20

算法实现:

算法伪代码:

上述算法显然时间复杂度时O(n),空间复杂度是O(n)。

算法结果

输出结果(取一次)

复杂度分析

三种算法在不同规模下运行时间如下表:

纵坐标单位为(ms),横坐标单位为(个)。

当问题规模到15000时,暴力算法明显变得笨重;当问题规=规模到达10000000时,分治算法也开始劣于动态规划。

三者的时间复杂度比较:O(n2)>O(nlogn)>O(n)。

源代码

暴力算法:

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import java.util.Scanner;public class ziduanhe1 {public static int []a = new int[1000000];public static void test(int n){random_get(n);int ThisSum,MaxSum=0;for (int i = 0; i < n; i++) {ThisSum = 0;for (int j = i; j < n; j++) {ThisSum+=a[j];if (ThisSum>MaxSum){MaxSum = ThisSum;}}}System.out.print(MaxSum);}public static int random_get(int l){Random r = new Random();int c = 40;for (int i = 0; i < l; i++) {a[i]= r.nextInt(c)%(2*c+1)-c/2;}return 0;}public static void main(String[] args){int n;Scanner sc = new Scanner(System.in);while (sc.hasNext()) {n = sc.nextInt();
//        for (int i = 0; i < n; i++) {//            a[i] = sc.nextInt();
//        }
//        ziduanhe1 t = new ziduanhe1();long startTime = System.currentTimeMillis();SimpleDateFormat df = new SimpleDateFormat("\n" + "yyyy-MM-dd HH:mm:ss");System.out.println(df.format(new Date()));test(n);long endTime = System.currentTimeMillis();System.out.println(df.format(new Date()));System.out.println("\n" + "执行时间" + (endTime - startTime) + "ms");}}
}

分治算法:

import java.text.SimpleDateFormat;
import java.util.*;
public class ziduanhe2
{public static int []a =new int[101000000];public static int maxsum(int l,int r){if(l==r){return a[l];}int mid = (l+r)/2;int lsum = maxsum(l,mid);//左区间int rsum = maxsum(mid+1,r);//右区间int sum1=0,sum2=0;int lefts=0,rights=0;for(int i=mid;i>=l;i--){lefts+=a[i];if(lefts>sum1){sum1=lefts;}}for(int i=mid+1;i<=r;i++){rights+=a[i];if(rights>sum2){sum2=rights;}}int msum=sum1+sum2;return Math.max(Math.max(lsum,rsum),msum);}public static int random_get(int l){Random r = new Random();int c = 40;for (int i = 0; i < l; i++) {a[i]= r.nextInt(c)%(2*c+1)-c/2;}return 0;}public static void main(String[] args){int n;int ans;Scanner in=new Scanner(System.in);while(in.hasNext()){n=in.nextInt();
//            for(int i=1;i<=n;i++){//                a[i]=in.nextInt();
//            }random_get(n);long startTime = System.currentTimeMillis();SimpleDateFormat df = new SimpleDateFormat("\n"+"yyyy-MM-dd HH:mm:ss");System.out.println(df.format(new Date()));ans = maxsum(0,n);if(ans<0){ans=0;}System.out.println(ans);long endTime = System.currentTimeMillis();System.out.println(df.format(new Date()));System.out.println("\n"+"执行时间"+(endTime-startTime)+"ms");}}
}

动态规划:

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import java.util.Scanner;public class ziduanhe3 {public static int []a = new int[101000000];public static int maxSum(int n){random_get(n);
//        for (int i = 0; i < n; i++) {//            System.out.print(a[i]);
//        }int sum = 0;int b = 0;for (int i = 0; i < n; i++) {if (b>0) b+=a[i];else b = a[i];if (sum<b) sum = b;}return sum;}public static int random_get(int l){Random r = new Random();int c = 40;for (int i = 0; i < l; i++) {a[i]= r.nextInt(c)%(2*c+1)-c/2;}return 0;}public static void main(String[] args){Scanner sc = new Scanner(System.in);int n;int ans = 0;System.out.print("请输入元素个数:");while (sc.hasNext()){n =sc.nextInt();
//            for (int i = 0; i < n; i++) {//                a[i] = sc.nextInt();
//            }long startTime = System.currentTimeMillis();SimpleDateFormat df = new SimpleDateFormat("\n"+"yyyy-MM-dd HH:mm:ss");System.out.println(df.format(new Date()));ans = maxSum(n);if (ans<0){ans = 0;}System.out.print("最大子段和:");System.out.print(ans);long endTime = System.currentTimeMillis();System.out.println(df.format(new Date()));System.out.println("\n"+"执行时间"+(endTime-startTime)+"ms");}}
}

最大子段和三种算法实现相关推荐

  1. 爱因斯坦谜题解答(三种算法比较)

    爱因斯坦谜题:     在一条街上有颜色互不相同的五栋房子,不同国籍的人分别住在这五栋房子力,每人抽不同品牌的香烟,喝不同的饮料,养不同的宠物.已知如下情况: 1.  英国人住红色房子里. 2.  瑞 ...

  2. EL之DTRFGBT:基于三种算法(DT、RF、GBT)对泰坦尼克号乘客数据集进行二分类(是否获救)预测并对比各自性能

    EL之DT&RF&GBT:基于三种算法(DT.RF.GBT)对泰坦尼克号乘客数据集进行二分类(是否获救)预测并对比各自性能 目录 输出结果 ​设计思路 核心代码 输出结果 设计思路 核 ...

  3. java 求最大公因数_求最大公约数的三种算法(java实现)

    三种算法: //欧几里得算法(辗转相除): public static int gcd(int m,int n) { if(m int k=m; m=n; n=k; } //if(m%n!=0) { ...

  4. SQL Server 索引基础知识(10)----Join 时的三种算法简介

    我们书写查询语句的时候,Join 参数之前可以是下面三个 { LOOP | MERGE | HASH } JOIN  . 如果不使用,则系统自己分析那种方式快,使用那种方式. 这其实是SQL Serv ...

  5. c语言求最小公倍数和最大公约数三种算法

    C语言求最小公倍数和最大公约数三种算法(经典) 求最小公倍数算法: 最小公倍数=两整数的乘积÷最大公约数 求最大公约数算法: (1)辗转相除法 有两整数a和b: ① a%b得余数c ② 若c=0,则b ...

  6. 三种算法求两个正整数的最大公约数和最小公倍数;求三个数的最大公约数和最小公倍数

    第二次作业 题目:求两个正整数的最大公约数和最小公倍数. 基本要求:1.程序风格良好(使用自定义注释模板),两种以上算法解决最大公约数问题,提供友好的输入输出. 提高要求:1.三种以上算法解决两个正整 ...

  7. C语言求最小公倍数和最大公约数三种算法(经典)

    C语言求最小公倍数和最大公约数三种算法(经典) 最小公倍数:数论中的一种概念,两个整数公有的倍数成为他们的公倍数,其中一个最小的公倍数是他们的最小公倍数,同样地,若干个整数公有的倍数中最小的正整数称为 ...

  8. 【老生谈算法】matlab实现EKF UKF PF三种算法对比源码——EKF UKF PF算法

    EKF UKF PF三种算法对比 matlab程序 1.文档下载: 本算法已经整理成文档如下,有需要的朋友可以点击进行下载 序号 文档(点击下载) 本项目文档 [老生谈算法]EKF-UKF-PF三种算 ...

  9. 冒泡排序,插入排序,选择排序三种算法的优劣

    https://www.jianshu.com/p/9f724c880124 最近听了王争老师的数据结构与算法之美,大有获益,特写此博客与大家分享. 排序算法太多了,但大体可以归结于三类,冒泡排序,插 ...

  10. 最短路小结(三种算法+各种常见变种)

    额,博主只是做了几(约数)道题而已,写这篇小结纯粹想留作纪念(勿喷,但是可以交流)(那啥,转载的话注明一下来源..打字不容易..) 最短路呢,包括三种算法,但是各有各的变种,其中变化有很多. 简单记录 ...

最新文章

  1. MySQL数学函数简明总结
  2. 怎样向IT行业的朋友说明《圣经》的重要性
  3. Android监听SD卡文件变化
  4. 安装windows系统时遇到的大坑——鼠标键盘没反应
  5. Python itertools模块
  6. c语言程序设计dowhile,(C语言while、dowhile、for循环课程5.docx
  7. AAAI2021论文合集汇总!(持续更新)
  8. 129. Sum Root to Leaf Numbers
  9. 一个SAP开发人员的养蚕流水帐
  10. SDN精华问答 | 为什么会出现SDN?
  11. JavaMail发送邮件的笔记及Demo
  12. 计算机硬盘驱动器越大,计算机基础知识1.3摘要.doc
  13. 展厅智能中央控制服务器,可视化展馆智能中控-智能中央控制系统
  14. centos7 安装node
  15. Java高级:面试题-1
  16. 大数据的三大理念解析
  17. MIRACL大数运算库使用手册
  18. android mac地址不可用,Android手机里的mac地址显示不可用是为什么。我的手机是海信E920....
  19. 安卓打造自己的日历控件
  20. 解决enter键Typora不能单换行的问题

热门文章

  1. MCSA Server 2012 R2 IPV6
  2. Qt QDir用法及实战案例
  3. linux系统如何使用GPT工具进行分区
  4. diskgenius创建efi分区_怎么创建efi系统分区?efi系统分区创建教程
  5. 【python 保存生成的图片 (plt;opencv;PIL)】
  6. 阿里maven仓库地址
  7. android接收红外传感器发送的脉冲信号,Arduino红外传感器-IR Receiver Module红外接收模块...
  8. 扩展欧几里得算法(简单易懂,详细分析)
  9. IP变更导致fdfs文件上传服务不可用解决流程
  10. 酷柚易汛工资条代码全开源,方便二次开发