标签:
思路来自算法导论,将数组平分为左右两个子数组,那么最大子数组可能在左边的子数组中,也有可能在右边的子数组中,还有可能跨过中间的元素,只有这三种情况。对于前两种情况,可以使用递归求解,对于第三种情况,可以做到用线性时间复杂度的函数来求解,详见代码。
#include <iostream> #include <map> using namespace std; //the thought of this algrithm is devide-and-couque int int_max = 0x7fffffff;//int类型的最大值,二进制最前面一位代表符号 int int_min = 0x80000000;//int类型的最小值 struct array_data{ int low; int high; int sum; }; array_data* find_max_subarray(int* A, int low,int high); array_data* find_max_crossing_subarray(int* A, int low, int high); //find the max subarray which crosses middle element //这段代码的复杂度是线性的(O(n)) array_data* find_max_crossing_subarray(int* A, int low, int high){ int mid = (low+high) >> 1; int left_sum = int_min; int sum = 0; int max_left = 0;//初始点的选取无所谓,因为数组的和肯定比int_min要大 //从中间开始依次往左边找sum最大的子树组 for(int i=mid; i>=low; i--){ sum = sum + A[i]; if(sum > left_sum){ left_sum = sum; max_left = i; } } //从中间开始依次往右边找sum最大的子树组 int right_sum = int_min; int max_right = mid+1;//初始认为中间往右第一个元素的位置为最大子树组的终点 sum = 0; for(int i=mid+1; i<=high; i++){ sum = sum + A[i]; if(sum > right_sum){ right_sum = sum; max_right = i; } } array_data* arr = new array_data(); arr->low = max_left; arr->high = max_right; arr->sum = left_sum + right_sum; return arr; } array_data* find_max_subarray(int* A,int low,int high){ if(low == high){ array_data* arr = new array_data(); arr->low = low; arr->high = high; arr->sum = A[low]; return arr;//base case: only one element }else{ int mid = (low+high) >> 1; //recursion left array_data* arr_left = find_max_subarray(A,low,mid); //recursion right array_data* arr_right = find_max_subarray(A,mid+1,high); //calc crossing middle array_data* arr_cross = find_max_crossing_subarray(A,low,high); //compare three situation int left_sum = arr_left->sum; int right_sum = arr_right->sum; int cross_sum = arr_cross->sum; if(left_sum >= right_sum && left_sum >= cross_sum){ return arr_left; }else if(right_sum >= left_sum && right_sum >= cross_sum){ return arr_right; }else{ return arr_cross; } } } int main(){ int A[] = {-1,2,4,-2,-4,4,9,-3,2};//注意初始化时必须是数组 int low = 0; int high = sizeof(A)/sizeof(A[0])-1; array_data* arr_done = find_max_subarray(A,low,high); //output A[] for(int i=0;i<= high;i++){ cout<<A[i]<<" "; } cout<<endl; cout<<"low:"<<arr_done->low<<" high:"<<arr_done->high<<" sum:"<<arr_done->sum<<endl; return 0; }
标签:
原文地址:http://www.cnblogs.com/lengyue365/p/5080388.html