採用分治策略求最大子段和的問題
/*
* 一個數組中的最大子段和有三種情況
* 只有一個元素時,最大子段和就是這個元素
* 超過一個元素時,採用分治策略(遞歸),進行劃分,遞歸求解
* 可能在中間值的左側,也可能在右側,也可能是跨過中間值
* 把這三種情況都列出來,然後最後比較這三種情況求得的子段和的大小
*/
求解方法:
package 最大子段和問題;
public class Max_Sum {
/*
* 一個數組中的最大子段和有三種情況
* 只有一個元素時,最大子段和就是這個元素
* 超過一個元素時,採用分治策略(遞歸),進行劃分,遞歸求解
* 可能在中間值的左側,也可能在右側,也可能是跨過中間值
* 把這三種情況都列出來,然後最後比較這三種情況求得的子段和的大小
*/
public int max_sum(int a[],int left,int right)
{
int sum=0;//記錄最大子段和
//如果數組中只有一個元素,且該元素大於0,則sum爲它本身,如果小於0,sum=0
if(left==right)
{
if(a[left]>=0)
sum=a[left];
else
sum=0;
}
//如果數組中的元素不止一個,則需要進行劃分
else
{
int center=0;//存放中間的數
int leftsum=0;//中間值左側的最大子段和
int rightsum=0;//中間值右側的最大子段和
center=(left+right)/2;
//最大子段和在左側
leftsum=max_sum(a,left,center);//遞歸求左側的最大子段和
//最大子段和在右側
rightsum=max_sum(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 j=center+1;j<=right;j++)
{
rights+=a[j];
if(rights>s2)
{
s2=rights;
}
}
sum=s1+s2;
if(sum<leftsum)
{
sum=leftsum;
}
if(sum<rightsum)
{
sum=rightsum;
}
}
return sum;
}
}
測試類
package 最大子段和問題;
import java.util.Scanner;
public class Main {
public static void main(String[] args)
{
Scanner cin=new Scanner(System.in);
int n;
n=cin.nextInt();
int a[]=new int[n];
for(int i=0;i<n;i++)
{
a[i]=cin.nextInt();
}
Max_Sum ms=new Max_Sum();
int sum=ms.max_sum(a, 0, n-1);
System.out.println(sum);
cin.close();
}
}