分治——最大子数组问题
样例:A={13,-3,-25,20,-3,-16,-23,18,20,-7,12,-15,-22,15,-4,7},最大子数组为A[7~10],和为43。
思路:先求出跨中点的最大子数组,再递归的求解左边一半的最大子序列和右边一半的最大子序列,以此类推。
伪代码:
FIND_MAX_CROSSING_SUBARRAY(A,low,mid,high) left_sum=A[mid] //注意是left_sum=A[mid]不是left_sum=负无穷,书上错了!! sum=0; for i=mid downto low //第一次不执行这句!!因为mid==low==0!! sum=sum+A[i] if sum>left_sum left_sum=sum max_left=i right_sum=A[mid+1] //一样,书上错了!! sum=0 for i=mid+1 to high //注意!这里是mid+1 sum=sum+A[i] if sum>right_sum right_sum=sum max_right=i return(max_left,max_right,left_sum+right_sum) FIND_MAX_SUBARRAY(A,low,high) if high==low return(low,high,A[low]) else mid=[(low+high)/2] (left_low,left_high,left_sum)= FIND_MAX_SUBARRAY(A,low,mid) (right_low,right_high,right_sum)= FIND_MAX_SUBARRAY(A,mid+1,high) (cross_low,cross_high,cross_sum)= FIND_MAX_CROSSING_SUBARRAY(A,low,mid,high) if left_sum>=right_sum and left_sum>=cross_sum return(left_low,left_high,left_sum) else if right_sum>=left_sum and right_sum>=cross_sum return(right _low, right _high, right _sum) else return(cross_low,cross_high,cross_sum)
C语言代码(附调试):
#include<stdio.h> int FIND_MAX_CROSSING_SUBARRAY(int* A, int low, int mid, int high); int FIND_MAX_SUBARRAY(int* A, int low, int high); int main() { int A[16] = { 13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -15, -22, 15, -4, 7 }; int sum; sum=FIND_MAX_SUBARRAY(A,0,15); printf("%d\n", sum); printf("hello.."); system("pause"); return 0; } int FIND_MAX_SUBARRAY(int* A, int low, int high) { int mid, left_sum, right_sum, cross_sum; if (high == low) return(low, high, A[low]); else { mid = (low + high) / 2; // printf("mid=%d\n", mid); left_sum= FIND_MAX_SUBARRAY(A, low, mid); // printf("left_sum=%d\n", left_sum); right_sum = FIND_MAX_SUBARRAY(A, mid+1, high); // printf("right_sum=%d\n", right_sum); cross_sum = FIND_MAX_CROSSING_SUBARRAY(A, low, mid, high); // printf("low=%d\tmid=%d\thigh=%d\tcross_sum=%d\n", low,mid,high,cross_sum); } if (left_sum >= right_sum && left_sum >= cross_sum) return left_sum; else if (right_sum >= left_sum && right_sum >= cross_sum) return right_sum; else return cross_sum; } int FIND_MAX_CROSSING_SUBARRAY(int* A, int low, int mid, int high) { int left_sum, right_sum; left_sum = A[mid]; int sum = 0; int i; for (i = mid; i >low; i--) { sum = sum + A[i]; if (sum > left_sum) { left_sum = sum; } // printf("cross_left_sum=%d\n", left_sum); } right_sum = A[mid+1]; sum = 0; for (i = mid+1; i <high; i++) { sum = sum + A[i]; if (sum > right_sum) { right_sum = sum; } } // printf("cross_left_sum=%d\tcross_right_sum=%d", left_sum, right_sum); return left_sum + right_sum; }

浙公网安备 33010602011771号