最大子段分治法解法
阿新 • • 發佈:2019-02-11
#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; }