1. 程式人生 > >最大子段分治法解法

最大子段分治法解法

#include <string.h>
#include <stdio.h>
/**
 * 計算 a中從 left 到 right的最大子序列
 * l r為計算得到的子序列位置
 */
int maxSub(int *a, int left, int right, int *l, int *r) {
	if (left == right) {
		*l = left;
		*r = left;
		return a[left];
	}

	if (left + 1 == right) {
		if (a[left] > 0 && a[right] > 0) {
			*l = left;
			*r = right;
			return a[left] + a[right];
		} else if (a[left] > a[right]) {
			*l = left;
			*r = left;
			return a[left];
		} else {
			*l = right;
			*r = right;
			return a[right];
		}
	}

	int center = (left + right) / 2;
	int ll = 0, lr = 0;
	int sum1 = maxSub(a, left, center, &ll, &lr);
	int rl = 0, rr = 0;
	int i;
	int sum2 = maxSub(a, center + 1, right, &rl, &rr);

	if (sum1 > 0 && sum2 > 0) {

		//計算中間資料
		int tempsum = 0;
		int max = rl - 1;
		i = lr + 1;
		for (; i <= max; i++) {
			tempsum += a[i];
		}

		if (sum1 > sum2) {

			if (sum2 + tempsum > 0) {
				*l = ll;
				*r = rr;
				return sum1 + sum2 + tempsum;
			} else {

				*l = ll;
				*r = lr;

				return sum1;
			}
		} else {

			if (sum1 + tempsum > 0) {
				*l = ll;
				*r = rr;
				return sum1 + sum2 + tempsum;
			} else {
				*l = rl;
				*r = rr;
				return sum2;
			}
		}

	} else if (sum1 > sum2) {
		*l = ll;
		*r = lr;
		return sum1;
	} else {
		*l = rl;
		*r = rr;
		return sum2;
	}
}

int main(void) {

    int a[10] = {-4,-3,-3,3,0,0,-4,-3,-9,-1};
    int l=0,r=9;
    int sum=maxSub(a,0,9,&l,&r);
    printf("max from %d to %d sum is %d",l,r,sum);
    printf("\n");
}



 

在計算機演算法設計與分析中 給出了一個動態規劃演算法 如下

int MaxSub_(int n,int *a){

	int sum=0,b=0;
	int i=0;
	for(;i<=n;i++){
		if(b>0)
			b+=a[i];
		else
			b=a[i];
		if(b>sum)
			sum=b;

	}
	return sum;
}
演算法很簡單 不過演算法不能給出最大子段的位置 還有不能計算純負陣列成的序列

可以對演算法稍微做下改動使支援全部由負陣列成的序列

int MaxSub_(int n,int *a){


	int sum=1,b=0;
	int i=0;
	int size=sizeof(int);
//獲取最小整數
         sum=sum<<(size*8-1);
	printf("sum=%d %d",sum,size);
	for(;i<=n;i++){
		if(b>0)
			b+=a[i];
		else
			b=a[i];
		if(b>sum)
			sum=b;

	}
	return sum;
}