本文來自CSDN博客:http://blog.csdn.net/gaoyusi4964238/archive/2010/05/18/5605123.aspx
問題描述:
給定一個數據,求數據中相鄰元素的最大和。例如:對於數組[5,-6,5,3,6,-8],其相鄰元素最大和爲14(5+3+6)。
算法實現如下:
view plaincopy to clipboardprint?
package test;
import java.util.Random;
import org.junit.Test;
public class TestAlgorithm {
/**
* 對於數組分爲兩個大小基本相等的部分,那麼最大和集必然出現在以下三種情況下:
* <p>1.最大和集出現在前半部分內,或者是整個前半部分;
* <p>2.最大和集出現在後半部分內,或者是整個後半部分;
* <p>3.如果過既不出現在前半部分,也不出現在後半部分,那麼最大和必然橫跨前半部分和後半部分,
* 所以前半部分(假設a)和後半部分(假設b)的分割點(假設i)必然包含在最大和集中,那麼這時候只需要以i
* 爲起點向前求其最大和集(c1),向後求其最大和集(c2),那麼這種情況下最大和集爲c1+c2;
* <p>所以最大和集的求法即可採用分治算法,遞歸求出數組前半部分,後半部分,和整個部分的最大值即可。
*/
public int divideAndConquerSum(int[] a,int low,int high){
if(low>high)
return 0;
if(low==high)
return max(0,a[low]);
//求出在[low,high]內包含a[mid]的最大sum
int mid=(low+high)/2;
int isum=0;
int lsum=0;
int rsum=0;
for(int i=mid;i>=low;i--){
isum+=a[i];
lsum=max(isum,lsum);
}
isum=0;
for(int i=mid+1;i<=high;i++){
isum+=a[i];
rsum=max(isum,rsum);
}
return max(lsum+rsum,divideAndConquerSum(a,low,mid),divideAndConquerSum(a,mid+1,high));
}
/**
* 掃描算法
*/
public int scanningSum(int[] a){
int sum=0;
int tmpSum=0;
for(int i=0;i<a.length;i++){
//如果前i位之和爲負數,那麼說明前i位不可能包含在最大和集中,重置tmpSum
tmpSum=max(tmpSum+a[i],0);
sum=max(tmpSum,sum);
}
return sum;
}
public int max(int a,int b){
return a>b?a:b;
}
public int max(int a,int b,int c){
//System.out.println("a:"+a+";b:"+b+";c:"+c);
return max(a,max(b,c));
}
@Test
public void test(){
Random random=new Random();
int [] a=new int[random.nextInt(10)];
for(int i=0;i<a.length;i++){
a[i]=random.nextInt(100)-random.nextInt(100);
System.out.print(a[i]+",");
}
System.out.println("數組長度:"+a.length);
int dMax=divideAndConquerSum(a,0,a.length-1);
System.out.println("分治算法:"+dMax);
int sMax=scanningSum(a);
System.out.println("掃描算法:"+dMax);
}
}