求子段最大和问题
一、问题描述
问题: 给定n个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。当所给的整数均为负数时定义子段和为0,依此定义,所求的最优值为: Max{0,a[i]+a[i+1]+…+a[j]},1<=i<=j<=n
例如,当(a[1],a[2],a[3],a[4],a[5],a[6])=(-2,11,-4,13,-5,-2)时,最大子段和为20。
求解:关于求最大子段和的问题,本次运用暴力求解、暴力求解的优化、
分治算法、遍历算法四种方法进行求解。
二、程序算法
public class getMaxpd {
/*
* 暴力求解法
*
* 列举出所有的字段和、选出最大字段和
*
* Run Time O(N^3)
*/
public static int getMaxpd1(int[] arr){
int maxSum = 0;
for(int i = 0; i < arr.length;i++) {
for(int j = i; j < arr.length;j++) {
int sum = 0;
for(int k = i; k <= j;k++) {
sum += arr[k];
}
if(sum > maxSum) {
maxSum = sum;
}
}
}
return maxSum;
}
/*
* 暴力求解法的改进
*
* 去掉最后一次的循环过程
*
* Run Time O(N^*2)
*/
public static int getMaxpd2(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;
}
/*
* 分治算法三种情况:
* 1.最大的字段存在center以左
* 2.最大的字段存在center以右
* 3.最大的字段存在包括center的连续部分
*
* 找出后判断最大部分,用递归进行寻找
* Run Time O(N*logN)
*/
public static int getMaxpd3(int[] arr,int left,int right) {
if (left == right) {
if (arr[left] > 0) {
return arr[left];
} else {
return 0;
}
}
int center = (left+right)/2;
int maxLeftSum = getMaxpd3(arr,left,center);
int maxRightSum = getMaxpd3(arr,center+1,right);
//left-half's sum
int maxLeftAsideSum = 0,
leftAsideSum = 0;
for(int i = center; i >= left; i--) {
leftAsideSum += arr[i];
if(leftAsideSum > maxLeftAsideSum) {
maxLeftAsideSum = leftAsideSum;
}
}
//right-half's sum
int maxRightAsideSum = 0,
rightAsideSum = 0;
for(int i = center+1;i <= right; i++) {
rightAsideSum += arr[i];
if(rightAsideSum > maxRightAsideSum) {
maxRightAsideSum = rightAsideSum;
}
}
//has center sum
int centerSum = maxLeftAsideSum + maxRightAsideSum;
if(maxLeftSum > maxRightSum && maxLeftSum > centerSum) {
return maxLeftSum;
}else if (maxRightSum > maxLeftSum && maxRightSum > centerSum) {
return maxRightSum;
}else {
return centerSum;
}
}
/*
* 从Array的某一点,寻找到Array[i]的最大字段
* 置需要遍历一次数组
* Run Time O(N)
* The best in my functions
*/
public static int getMaxpd4(int arr[]) {
int maxSum =0,
sum = 0;
for(int i = 0; i < arr.length; i++) {
sum += arr[i];
if(sum > maxSum) {
maxSum = sum;
}else if(sum < 0) {
sum = 0;
}
}
return maxSum;
}
}
三、测试
(1)条件判定测试部分核心代码
public class getMaxpdTest {
@Test
public void testGetMaxpd0() {
int arr[] = {1,2,3,4,5,6};//全正用例
assertEquals(21,new getMaxpd().getMaxpd4(arr));
}
@Test
public void testGetMaxpd1() {
int arr[] = {1,2,-5,3,-15,4,5,-5,-1,2};//测试用例
assertEquals(9,new getMaxpd().getMaxpd4(arr));
}
@Test
public void testGetMaxpd2() {
int arr[] = {-1,-2,-100,-10};//全负测试用例
assertEquals(0,new getMaxpd().getMaxpd4(arr));
}
@Test
public void testGetMaxpd4() {
int arr[] = {-2,11,-4,13,-5,-2};//作业测试用例
assertEquals(20,new getMaxpd().getMaxpd4(arr));
}
}
(2)测试截图
四、总结
a.算法的逐步优化应该是每一个程序员不断探索的。
b.学会将项目或代码上传到coding中,用于以后的学习、阅读。
c.测试部分应该全面,实现全面覆盖,对于软件开发和维护有很大价值。