最大子段和问题Java实现
最大子段和问题
一、问题描述
给定长度为n的整数序列,a[1...n], 求[1,n]某个子区间[i , j]使得a[i]+…+a[j]和最大。
例如(-2,11,-4,13,-5,2)的最大子段和为20,所求子区间为[2,4],子序列是(11,-4,13),最大子段和是20。
二、解决方法
1、穷举法(初级版):SimpleAlgorithmOfMaximumIntervalSumLow.java
最容易理解,
用三重循环,可遍历所有子区间,一个表示起始位置,一个表示终点位置,一个求当前子序列的和
package cn.com.zfc.everyday.test; /** *
* @title SimpleAlgorithmOfMaximumSegmentSumLow
* @describe 最大子段和的简单算法的初级版
* @author 张富昌
* @date 2017年4月9日下午10:45:51
*/
public class SimpleAlgorithmOfMaximumIntervalSumLow {
// 最大子段和的首元素在原序列中的位置
private static int startIndex;
// 最大子段和的尾元素在原序列中的位置
private static int endIndex; public static void main(String[] args) {
// 原序列
int[] array = { -2, 11, -4, 13, -5, -2 };
System.out.println("原序列是:");
// 输出原序列
printSegment(0, array.length - 1, array);
// 求最大子段和
int maxSum = maxSum(array);
System.out.println("最大字段和:" + maxSum);
System.out.println("最大子段和的首元素在原序列中的位置:" + startIndex + ",最大子段和的尾元素在原序列中的位置:" + endIndex);
System.out.println("最大字段和的子序列式:");
// 输出最大子段和序列
printSegment(startIndex, endIndex, array);
} /**
*
* @param array:原序列
* @return:最大子段和
*/
private static int maxSum(int[] array) {
// 假设最大子段和为 0
int maxSum = 0;
// 双重 for 循环遍历所有的子序列
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array.length; j++) {
// 一个 for 循环求当前子序列的和
int currentSum = 0;
for (int k = i; k <= j; k++) {
currentSum += array[k];
}
if (currentSum > maxSum) {
maxSum = currentSum;
// 最大子段和的首元素在原序列中的位置
startIndex = i;
// 最大子段和的尾元素在原序列中的位置
endIndex = j;
}
}
}
return maxSum;
} /**
* 输出序列
*
* @param start:序列的开始下标
* @param end:序列的结束下标
* @param array:要输出的序列
*/
private static void printSegment(int start, int end, int[] array) {
for (int i = start; i <= end; i++) {
System.out.print(array[i] + " ");
}
System.out.println();
} }
2、穷举法(升级版):SimpleAlgorithmOfMaximumIntervalSumHigh.java
避免子序列的重复计算
package cn.com.zfc.everyday.test; /**
*
* @title SimpleAlgorithmOfMaximumIntervalSumHigh
* @describe 最大子段和的简单算法的升级版
* @author 张富昌
* @date 2017年4月9日下午11:17:33
*/
public class SimpleAlgorithmOfMaximumIntervalSumHigh {
// 最大子段和的首元素在原序列中的位置
private static int startIndex;
// 最大子段和的尾元素在原序列中的位置
private static int endIndex; public static void main(String[] args) {
// 原序列
int[] array = { -2, 11, -4, 13, -5, -2 };
System.out.println("原序列是:");
// 输出原序列
printSegment(0, array.length - 1, array);
// 求最大子段和
int maxSum = maxSum(array);
System.out.println("最大字段和:" + maxSum);
System.out.println("最大子段和的首元素在原序列中的位置:" + startIndex + ",最大子段和的尾元素在原序列中的位置:" + endIndex);
System.out.println("最大字段和的子序列式:");
// 输出最大子段和序列
printSegment(startIndex, endIndex, array);
} /**
*
* @param array:原序列
* @return:最大子段和
*/
private static int maxSum(int[] array) {
// 假设最大子段和为 0
int maxSum = 0;
// 双重 for 循环遍历所有的子序列
for (int i = 0; i < array.length; i++) {
// 当前序列的和
int currentSum = 0;
// 注意 j 的初始值,避免重复计算
for (int j = i; j < array.length; j++) {
currentSum += array[j];
if (currentSum > maxSum) {
maxSum = currentSum;
// 最大子段和的首元素在原序列中的位置
startIndex = i;
// 最大子段和的尾元素在原序列中的位置
endIndex = j;
}
}
}
return maxSum;
} /**
* 输出序列
*
* @param start:序列的开始下标
* @param end:序列的结束下标
* @param array:要输出的序列
*/
private static void printSegment(int start, int end, int[] array) {
for (int i = start; i <= end; i++) {
System.out.print(array[i] + " ");
}
System.out.println();
} }
3、分治算法:BranchAlgorithmOfMaximumIntervalSum.java
package cn.com.zfc.everyday.test; /**
*
* @title BranchAlgorithmOfMaximumIntervalSum
* @describe 最大子段和的分治算法:
* 所有子区间[start, end]只可能有以下三种可能性:
* 在[1,n/2]这个区域内
* 在[n/2+1,n]这个区域内
* 起点位于[1,n/2],终点位于[n/2+1,n]内
* 以上三种情形的最大者,即为所求.
* 前两种情形符合子问题递归特性,所以递归可以求出. 对于第三种情形,则需要单独处理.
* 第三种情形必然包括了n/2和n/2+1两个位置,这样就可以利用第二种穷举的思路求出:
* 以n/2为终点,往左移动扩张,求出和最大的一个startSum,以n/2+1为起点,往右移动扩张,求出和最大的一个endSum
* startSum + endSum是第三种情况可能的最大值
* @author 张富昌
* @date 2017年4月9日下午10:46:32
*/
public class BranchAlgorithmOfMaximumIntervalSum { public static void main(String[] args) {
// 原序列
int[] array = { -2, 11, -4, 13, -5, -2 };
System.out.println("原序列是:");
// 输出原序列
printSegment(0, array.length - 1, array);
// 求最大子段和
int maxSum = maxSum(array);
System.out.println("最大字段和:" + maxSum);
} private static int maxSum(int[] array) {
return maxSubSum(array, 1, array.length - 1);
} private static int maxSubSum(int[] array, int start, int end) {
int sum = 0;
if (start == end) {
sum = array[start] > 0 ? array[end] : 0;
} else {
int center = (start + end) / 2;
// 以n/2为终点,往左移动扩张,求出和最大的一个startSum
int startSum = maxSubSum(array, start, center);
// 以n/2+1为起点,往右移动扩张,求出和最大的一个endSum
int endSum = maxSubSum(array, center + 1, end);
int s1 = 0;
int starts = 0;
// 以n/2为终点,往左移动扩张,求出和最大的一个 startSum
for (int i = center; i >= start; i--) {
starts += array[i];
if (starts > s1) {
s1 = starts;
}
}
int s2 = 0;
int ends = 0;
// 以n/2+1为起点,往右移动扩张,求出和最大的一个 endSum
for (int i = center + 1; i <= end; i++) {
ends += array[i];
if (ends > s2) {
s1 = ends;
}
}
sum = s1 + s2;
if (sum < startSum) {
sum = startSum;
}
if (sum < endSum) {
sum = endSum;
}
}
return sum;
} /**
* 输出序列
*
* @param start:序列的开始下标
* @param end:序列的结束下标
* @param array:要输出的序列
*/
private static void printSegment(int start, int end, int[] array) {
for (int i = start; i <= end; i++) {
System.out.print(array[i] + " ");
}
System.out.println();
} }
4、动态规划算法
package cn.com.zfc.everyday.test; /**
*
* @title DynamicProgrammingOfMaximumIntervalSum
* @describe 最大子段和的动态规划算法
* @author 张富昌
* @date 2017年4月9日下午10:47:00
*/
public class DynamicProgrammingOfMaximumIntervalSum {
public static void main(String[] args) {
// 原序列
int[] array = { -2, 11, -4, 13, -5, -2 };
System.out.println("原序列是:");
// 输出原序列
printSegment(0, array.length - 1, array);
// 求最大子段和
int maxSum = maxSum(array);
System.out.println("最大字段和:" + maxSum);
} /**
*
* @param array:原序列
* @return:最大子段和
*/
private static int maxSum(int[] array) {
int sum = 0;
int b = 0;
for (int i = 0; i < array.length; i++) {
if (b > 0) {
b += array[i];
} else {
b = array[i];
}
if (b > sum) {
sum = b;
}
}
return sum;
} /**
* 输出序列
*
* @param start:序列的开始下标
* @param end:序列的结束下标
* @param array:要输出的序列
*/
private static void printSegment(int start, int end, int[] array) {
for (int i = start; i <= end; i++) {
System.out.print(array[i] + " ");
}
System.out.println();
}
}
最大子段和问题Java实现的更多相关文章
- Spark案例分析
一.需求:计算网页访问量前三名 import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} /* ...
- 动态规划: 最大m子段和问题的详细解题思路(JAVA实现)
这道最大m子段问题我是在课本<计算机算法分析与设计>上看到,课本也给出了相应的算法,也有解这题的算法的逻辑.但是,看完之后,我知道这样做可以解出正确答案,但是我如何能想到要这样做呢? 课本 ...
- (Java实现) 洛谷 P1115 最大子段和
题目描述 给出一段序列,选出其中连续且非空的一段使得这段和最大. 输入输出格式 输入格式: 第一行是一个正整数NN,表示了序列的长度. 第二行包含NN个绝对值不大于1000010000的整数A_iA ...
- P1115_最大子段和(JAVA语言)
思路:贪心.累加求和,若和小于0则设置和为0,因为和小于0时对这段序列和无正作用,只会使整体变小,所以我们把小于0的段舍弃,从下一个数开始求序列和. 题目描述 给出一段序列,选出其中连续且非空的一段使 ...
- (转)java读取数据库表信息,子段
import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sq ...
- Java实现 洛谷 P1115 最大子段和
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scann ...
- 黑马程序员——【Java基础】——泛型、Utilities工具类、其他对象API
---------- android培训.java培训.期待与您交流! ---------- 一.泛型 (一)泛型概述 1.泛型:JDK1.5版本以后出现的新特性,用于解决安全问题,是一个类型安全机制 ...
- Java后台工程师面试杂记——不跳不涨工资星人跳槽经历
经过接近一个月的时间,完成换工作这件“小事”,前后总计面试了多家公司,最后也没接到几个offer,不过最终总算尘埃落定,就对这个过程进行一个总结吧. 在某互联网公司工作了近一年的时间,但是频繁的业务需 ...
- hdu 5586 Sum【dp最大子段和】
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5586 Sum Time Limit: 2000/1000 MS (Java/Others) Me ...
随机推荐
- atan2 atan
atan2 definition In terms of the standard arctan function, whose range is (−π/2, π/2), it can be exp ...
- Spring4笔记1--Spring概述、IoC
Spring概述: Spring框架: Spring 由 20 多个模块组成,它们可以分为数据访问/集成(Data Access/Integration).Web.面向切面编程(AOP, Aspec ...
- C# 所生成项目的处理器架构“MSIL”与引用“Oracle.DataAccess, Version=4.112.3.0, Culture=neutral, PublicKeyToken=89b483f429c47342, processorArchitecture=x86”的处理器架构“x86”不匹配。这种不匹配可能会导致运行时失败。
这个问题一般都是Oracle.DataAccess的版本不兼容问题造成的. 解决办法: 1.把Oracle.DataAccess.dll文件拿到C盘或D盘的安装文件的地方进行搜索. 2.会出现在pro ...
- django Rest Framework----GenericAPIView 通用视图 GenericAPIView源码分析
一.GenericAPIView GenericAPIView扩展了APIView,为标准列表和详细视图添加了常见的行为. 提供的每个具体通用视图都是一个GenericAPIView或多个mixin类 ...
- MAVLink v1.0详解——结构
本文针对 MAVLink v1.0版本,协议版本:3. MAVLink是为微型飞行器MAV(Micro Air Vehicle)设计的(LGPL)开源的通讯协议.是无人飞行器和地面站(Ground C ...
- 170406回顾-SQL Server的smalldatetime类型比较
在比较SQL Server的类型为smalldatetime字段时出现下面的错误:将 expression 转换为数据类型 smalldatetime 时出现算术溢出错误 正确的比较方法如下:将lon ...
- git —— 基本命令以及操作(No.1)
git基本命令(附加描述) 1.把文件添加到暂存区$ git add readme.txt 2.把暂存区的文件文件添加到仓库$ git commit -m "提交说明" 备注:ad ...
- 洛谷P3811乘法逆元
传送门 线性递推 #include <iostream> #include <cstdio> #include <cstring> #include <alg ...
- 16/11/22_plsql
1.数据类型: char 固定长度,varchar 字符长度按照实际长度, varchar2 字符均存储2个字节, nvarchar 按照Unicode存储.number(m,n)总长度m,小数 n. ...
- 【[SDOI2009]Bill的挑战】
一看题解好像全是状压DP,那么我就来补充一个容斥写法吧 乍一看,好像是水题,枚举选哪k个串,然后判断 1,如果这k个串中至少两个串某位置确定且不相同,答案显然为02,如果这个位置只被有且仅有一个串确定 ...