最大子段和的求解問題

採用分治策略求最大子段和的問題

/*
     * 一個數組中的最大子段和有三種情況
     * 只有一個元素時,最大子段和就是這個元素
     * 超過一個元素時,採用分治策略(遞歸),進行劃分,遞歸求解
     * 可能在中間值的左側,也可能在右側,也可能是跨過中間值
     * 把這三種情況都列出來,然後最後比較這三種情況求得的子段和的大小
     */

求解方法:

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();
	}
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章