/**
* 一维最大字段和问题,约定如果全部元素均是负数,
* 则最大字段和为0(不选任何元素)。
* @author Sking
*/
package 数组问题;
public class 一维最大子段和 {
/**
* 暴力遍历求解最大字段和问题
* 时间复杂度为O(n^3)
* @param a 指定序列
* @return 最大字段和
*/
public static int maxSum0(int[] a){
int n=a.length-1;
int sum=0;
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j++){
int thissum=0;
for(int k=i;k<=j;i++)thissum+=a[k];
if(thissum>sum)
sum=thissum;
}
return sum;
}
/**
* 改进的暴力遍历求解最大字段和问题
* 时间复杂度为O(n^2)
* @param a 指定序列
* @return 最大字段和
*/
public static int maxSum1(int[] a) {
int n = a.length - 1;
int sum = 0;
for (int i = 1; i <= n; i++) {
int thissum = 0;
for (int j = i; j <= n; j++) {
thissum += a[j];
if (thissum > sum) {
sum = thissum;
}
}
}
return sum;
}
/**
* 递归分治求最大字段和问题
* 求一个序列的最大字段和可以递归分为左右两个字段分析,
* 分别求左右字段的最大字段和,以及从中间开始向两边伸展
* 的最大字段和,则该序列的最大字段和是它们三者之一。
* 时间复杂度为:O(n*log2(n))
* @param a 指定序列
* @param left 序列的左端索引
* @param right 序列的右端索引
* @return 序列的最大字段和
*/
public static int maxSum2(int[] a,int left, int right) {
int sum = 0;
if (left == right)//只有一个元素
sum = a[left] > 0 ? a[left] : 0;
else {
int center = (left + right) / 2;
//递归求左右字段的最大字段和
int leftsum = maxSum2(a,left, center);
int rightsum = maxSum2(a,center + 1, right);
int s1 = 0;//从中间向左边伸展的最大字段和
int lefts = 0;
for (int i = center; i >= left; i--) {
lefts += a[i];
if (lefts > s1)
s1 = lefts;
}
int s2 = 0;//从中间向右边伸展的最大字段和
int rights = 0;
for (int i = center + 1; i <= right; i++) {
rights += a[i];
if (rights > s2)
s2 = rights;
}
sum = s1 + s2;
if (sum < leftsum)
sum = leftsum;
if (sum < rightsum)
sum = rightsum;
}
return sum;
}
/**
* 动态规划算法求解最大字段和问题:
* 假设(A[i],...,A[n-1])序列的最大字段和为all[i],
* (A[i],...,A[n-1])序列中包含A[i]的最大字段和为start[i],
* 则(A[i-1],A[i],...,A[n-1])序列的最大字段和为:
* max{A[i-1],A[i-1]+start[i],All[i]}.
* 性能:时间复杂度为O(n),辅助空间为2n
* 时间复杂度为:O(n)
* @param a 指定序列
* @return 最大字段和
*/
public int maxSum3(int[] a) {
int len=a.length;
int[] start=new int[len];
int[] all=new int[len];
start[len-1]=a[len-1];
all[len-1]=a[len-1];
for(int i=len-2;i>=0;i--){
start[i]=Math.max(a[i], a[i]+start[i+1]);
all[i]=Math.max(start[i], all[i+1]);
}
return all[0];
}
/**
* 动态规划算法求解最大字段和问题:
* 假设(A[i],...,A[n-1])序列的最大字段和为all[i](存在nAll)
* (A[i],...,A[n-1])序列中包含A[i]的最大字段和为start[i](存在nStart)
* 则(A[i-1],A[i],...,A[n-1])序列的最大字段和为:
* max{A[i-1],A[i-1]+nStart,nAll}.
* 性能:时间复杂度为O(n),辅助空间为2(即O(1))
* 时间复杂度为:O(n)
* @param a 指定序列
* @return 最大字段和
*/
public int maxSum4(int[] a) {
int len=a.length;
int nStart=a[len-1];
int nAll=a[len-1];
for(int i=len-2;i>=0;i--){
nStart=Math.max(a[i], a[i]+nStart);
nAll=Math.max(nStart, nAll);
}
return nAll;
}
/**
* 高效的动态规划求解最大字段和问题
* 时间复杂度为:O(n),辅助空间为2
* @param a 指定序列
* @return 最大字段和
*/
public int maxSum5(int[] a) {
int n = a.length;
int sum = 0;//最大字段和
int b = 0;//当前最大字段和
for (int i = 0; i <n; i++) {
if (b > 0)
b += a[i];
else
b = a[i];
if (b > sum)
sum = b;
}
return sum;
}
}
数组问题之一维最大字段和问题<Java实现>
最新推荐文章于 2020-08-10 11:18:03 发布