最大子段和问题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 ...
随机推荐
- XSS姿势——文件上传XSS
XSS姿势--文件上传XSS 原文链接:http://brutelogic.com.br/blog/ 0x01 简单介绍 一个文件上传点是执行XSS应用程序的绝佳机会.很多网站都有用户权限上传个人资料 ...
- Dream------Hadoop--HDFS的设计
HDFS是为以流式数据访问模式存储超大文件而设计的文件系统. 流式数据访问 HDFS建立在这样一个思想上:一次写入.多次读取模式是最高效的.一个数据集通常由数据源生成或复制, 接着在此基础上进行各 ...
- python3之线程与进程
1.CPU运行原理 我们都知道CPU的根本任务就是执行指令,对计算机来说最终都是一串由“0”和“1”组成的序列.CPU从逻辑上可以划分成3个模块,分别是控制单元.运算单元和存储单元,这三部分由CPU内 ...
- linux中断申请之request_threaded_irq 【转】
转自:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=21977330&id=3755609 在linux里,中断处理分 ...
- ubuntu使用百度云盘插件
Firefox 插件地址 https://addons.mozilla.org/zh-CN/firefox/addon/baidu-pan-exporter/ 安装后重启Firefox,然后百度云下载 ...
- RestTemplate中文乱码问题(spring-web3.0.7版本)
从网上找的方法: 方法一: //resttemplate乱码问题 //3.1.X以上版本使用 // restTemplate.getMessageConverters().add(0, StringH ...
- Flask:cookie 和 session (0.1)
Windows 10家庭中文版,Python 3.6.4,Flask 1.0.2 Cookie是什么?有什么用? 某些网站为了辨别用户身份.进行 session 跟踪而储存在用户本地终端上的数据(通常 ...
- 基于timestamp和nonce的防止重放攻击方案
参考:http://blog.csdn.net/koastal/article/details/53456696
- 用js面向对象思想封装插件
js是基于原型的面向对象语言,如果你学过java,c#等正统面向对象语言,你会难以理解js的面向对象,他和普通的面向对象不太一样,今天,我们通过封装一个toast插件,来看看js面向对象是如何运行的. ...
- 深度解析eclipse控制台
第一个按钮:scroll lock 控制台在打印sql语句的时候会一直滚动,用这个按钮可以固定住控制台不乱跑; 第二个按钮:show console when standard out changes ...