implement The Maximum Subarray using divide and conquer

分3种情况,1.最大子段和可能整段在数组的左边,2.可能在数组的右边 3.也可能穿过中点先分析过中点的情况。可以先从中间元素开始向两边求出左右各自的最大子段和,然后合并,《算法导论》给出的 pseudocode 如下:
FIND_MAX_CROSSING_SUBARRAY(A, low, mid, high)
left_sum = -∞
sum = 0
for i = mid downto low
    sum = sum + A[i]
    if sum>left_sum
        left_sum = sum
        max_left = i
right_sum = -∞
sum = 0
for j = mid+1 to high
    sum = sum + A[j]
    if sum>right_sum
        right_sum = sum
        max_right = j
return (max_left, max_right, left_sum, right_sum)

 用分治法将针对于规模为n 的数组最大字段和的问题分解成规模为 n/2 ,仍然存在上述的3种情况,所以 将规模一直分解到 1.这样最大子段和就是其本身。
 FIND_MAXIMUM_SUBARRAY(A, low, high)
 if low = high
     return (low, high, A[low])
 else
     mid = floor((low+high)/2)
     (left_low,left_high,left_sum)
         = FIND_MAXIMUM_SUBARRAY(A, low, mid)
     (right_low,right_high,right_sum)
         = FIND_MAXIMUM_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)

  The time complexity is O(nlgn). 

# include <iostream>
# include <cmath>
using namespace std;
struct maximum_subarray{
	int index_low;
	int index_high;
	int max_sum;
};

maximum_subarray find_cross_max_sub(int a[], int low, int mid, int high);
maximum_subarray find_max_sub(int a[],int low,int high);

int main(){
    int a[16] = {13, -3, 20, -25, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7};
    maximum_subarray m_s;
	  m_s = find_max_sub(a, 0, 15);
		for(int i = 0; i< 16; ++i)
				cout<<a[i]<<" ";
		cout<<endl;
		cout<<"The maximum subarray ";
		for(i = m_s.index_low; i<=m_s.index_high; ++i)
				cout<<a[i]<<" ";
		cout<<endl;
	  cout<<"The sum of maximum subarray "<<m_s.max_sum<<endl;
	  return 0;
}

maximum_subarray find_cross_max_sub(int a[],int low, int mid, int high){
    int left_sum = -999;  //保证所有字段和都大于它 
	int sum = 0, max_left = 0;
	for(int i = mid; i>= low; i--){
        sum = sum + a[i];
		if(sum > left_sum){
			left_sum = sum;
			max_left = i;
		}
	}
	int right_sum = -999;
	int max_right = 0;
	sum = 0; 
	for(int j = mid+1; j<= high; j++){
		sum = sum + a[j];
		if(sum > right_sum){
			right_sum = sum;
			max_right = j;
		}
	}
	maximum_subarray  cross_m_s;
	cross_m_s.index_low = max_left;
	cross_m_s.index_high = max_right;
	cross_m_s.max_sum = left_sum+right_sum;
	return cross_m_s;
}

maximum_subarray find_max_sub(int a[], int low, int high){
	int mid;
	maximum_subarray m_s0;
	m_s0.index_low = low; m_s0.index_high = high; m_s0.max_sum = a[low];
	maximum_subarray m_s1, m_s2, cross_m_s;
	if(low == high)
		return m_s0;
	else{// divide and conquer 
		mid = floor((low+high)/2);
		m_s1 = find_max_sub(a,low, mid);
		m_s2 = find_max_sub(a,mid+1,high);
		cross_m_s = find_cross_max_sub(a,low,mid,high);
	}
	if(m_s1.max_sum>=m_s2.max_sum && m_s1.max_sum>=cross_m_s.max_sum)
		return m_s1;
	else if(m_s2.max_sum>=m_s1.max_sum && m_s2.max_sum>=cross_m_s.max_sum)
		return m_s2;
	else
		return cross_m_s;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值