连续子序列最大和问题精讲(java实现)
2018-03-10 14:32
369 查看
package com.lihe.test.collection;
import java.util.Scanner;
public class MaxSequenceSum {
/**
* @author limingyu
* 连续子序列最大和问题:给定(可能是负的)整数序列A1,A2,...An,寻找使的值最大的序列。
* 如果所有的整数都是负的,那么连续子序列的最大和是零。要求算法复杂度为O(N^2)
* 例如输入{-2,11,-4,13,-5,2}答案为20
* 输入{1,-3,4,-2,-1,6}答案是7
*/
public static void main(String[] args) {
int[] arr = new int[]{-2,11,-4,13,-5,2};
System.out.println(maxSequence(arr));
// int[] arr = new int[]{-2,11,-4,-13,-5,2};
// System.out.println("maxSequence1:" + maxSequence1(arr));
}
public static int maxSequence(int[] arr) {
int maxSum = 0;
for (int i = 0; i < arr.length; i++) {
int sum = 0;
for (int j = i; j < arr.length; j++) {
sum += arr[j];
if(sum > maxSum){ //每次求和都進行比較
maxSum = sum;
}
}
}
return maxSum;
}
/**
* 从左到右记录当前子序列的和sum,开始位置为seqStart,结束位置为seqEnd。
* 若currentSum不断增加,那么最大子序列的和maxSum也不断增加(不断更新maxSum,start,end)。
* 如果往前扫描中遇到负数,那么当前子序列的和将会减小。此时currentSum 将会小于maxSum,当然maxSum也就不更新。
* 如果currentSum降到0时,说明前面已经扫描的那一段就可以抛弃了,这时将currentSum置为0,并且seqStart为下一个位置。
* 然后,currentSum将从后面开始将这个子段进行分析,若有比当前maxSum大的子段,继续更新maxSum。这样一趟扫描结果也就出来了。
* 要求算法复杂度为O(N)
*/
public static int maxSequence1(int[] arr){
int maxSum = 0;
int currentSum = 0;
int seqStart = 0;//最大和子序列起始位置
int seqEnd = 0;//最大和子序列结束位置
for(int i = 0,j = 0; j < arr.length; j ++){
currentSum += arr[j];
if(currentSum > maxSum){
maxSum = currentSum;
seqStart = i;
seqEnd = j;
}
/**
* 定理:设Ai,j是满足Si,j<0的任意子序列,如果p>j,那么Ai,q不是最大连续子序列
* 如果一个子序列的和是负的,则它不可能是最大连续子序列的一部分,因为我们可以通过不包含他来得
* 一个更大的连续子序列。或所有与最大连续子序列相邻的连续子序列一定有负的(或0)和(否则会包含他们)
*/
else if(currentSum <= 0){
//当检测到一个负的子序列时,可以让i直接增加到j+1,抛弃掉之前的负子序列,重新开始。
i = j + 1;
currentSum = 0;
}
}
System.out.println("start :" + seqStart + " end : "+ seqEnd);
return maxSum;
}
}
import java.util.Scanner;
public class MaxSequenceSum {
/**
* @author limingyu
* 连续子序列最大和问题:给定(可能是负的)整数序列A1,A2,...An,寻找使的值最大的序列。
* 如果所有的整数都是负的,那么连续子序列的最大和是零。要求算法复杂度为O(N^2)
* 例如输入{-2,11,-4,13,-5,2}答案为20
* 输入{1,-3,4,-2,-1,6}答案是7
*/
public static void main(String[] args) {
int[] arr = new int[]{-2,11,-4,13,-5,2};
System.out.println(maxSequence(arr));
// int[] arr = new int[]{-2,11,-4,-13,-5,2};
// System.out.println("maxSequence1:" + maxSequence1(arr));
}
public static int maxSequence(int[] arr) {
int maxSum = 0;
for (int i = 0; i < arr.length; i++) {
int sum = 0;
for (int j = i; j < arr.length; j++) {
sum += arr[j];
if(sum > maxSum){ //每次求和都進行比較
maxSum = sum;
}
}
}
return maxSum;
}
/**
* 从左到右记录当前子序列的和sum,开始位置为seqStart,结束位置为seqEnd。
* 若currentSum不断增加,那么最大子序列的和maxSum也不断增加(不断更新maxSum,start,end)。
* 如果往前扫描中遇到负数,那么当前子序列的和将会减小。此时currentSum 将会小于maxSum,当然maxSum也就不更新。
* 如果currentSum降到0时,说明前面已经扫描的那一段就可以抛弃了,这时将currentSum置为0,并且seqStart为下一个位置。
* 然后,currentSum将从后面开始将这个子段进行分析,若有比当前maxSum大的子段,继续更新maxSum。这样一趟扫描结果也就出来了。
* 要求算法复杂度为O(N)
*/
public static int maxSequence1(int[] arr){
int maxSum = 0;
int currentSum = 0;
int seqStart = 0;//最大和子序列起始位置
int seqEnd = 0;//最大和子序列结束位置
for(int i = 0,j = 0; j < arr.length; j ++){
currentSum += arr[j];
if(currentSum > maxSum){
maxSum = currentSum;
seqStart = i;
seqEnd = j;
}
/**
* 定理:设Ai,j是满足Si,j<0的任意子序列,如果p>j,那么Ai,q不是最大连续子序列
* 如果一个子序列的和是负的,则它不可能是最大连续子序列的一部分,因为我们可以通过不包含他来得
* 一个更大的连续子序列。或所有与最大连续子序列相邻的连续子序列一定有负的(或0)和(否则会包含他们)
*/
else if(currentSum <= 0){
//当检测到一个负的子序列时,可以让i直接增加到j+1,抛弃掉之前的负子序列,重新开始。
i = j + 1;
currentSum = 0;
}
}
System.out.println("start :" + seqStart + " end : "+ seqEnd);
return maxSum;
}
}
相关文章推荐
- 最大连续子序列问题的java实现
- “最长上升子序列,最大连续子序列和,最长公共子串”的Java实现
- java 之连续子序列最大和问题的四个解法
- java实现最大子序列问题——————性能最优的算法
- 总结java最大连续子序列和的问题
- [leetcode]分治法求解最大子序列问题——Java实现
- Java实现O(n)最大连续子序列和
- “最长上升子序列,最大连续子序列和,最长公共子串”的Java实现
- [java实现]找一个数组的最大和的连续子数组(时间复杂度 O(n))
- 数组问题之一维最大字段和问题<Java实现>
- 连续子向量的最大和问题(Python实现)
- 关于最大连续子序列和的问题 (Maximum Subsequence Sum Problem)
- 最长公共子序列问题-求所有公共子序列(java核心代码实现)
- 求最大连续子序列和问题
- 关于最大连续子序列问题
- 一维数组及子数组最大和问题Java实现
- 最大连续子序列之和问题
- 三种算法实现最大子段和问题(Java实现)
- 数字问题之最大公约数问题全解法归纳<Java实现>
- UVA 507 Jill Rides Again (连续子序列最大和问题)