分治法解决最大子数组问题 (C/C++)

问题背景

输入:数天内的股价变化情况(+10 代表上涨.-6 代表下降)
输出: 在某天买入,另一天卖出,获利最大的值

算法设计

抽象为一个数组
data={13,3,25,20,3,16,23,18,20,7,12,5,22,15,4,7}
求解最大的子数组.

采用分治的思想,利用中点把数组分为三类:
(设中点为mid,起始low,终点high,子数组界为i,j)
1. 左半部分: lowijmid
2. 跨越中点的部分: lowimidj<high
3. 右半部分: mid<ijhigh
对1,2两种情况进行分治并递归求解,3的算法设计则较为简单.

算法分析

(参见算法导论第四章)
时间复杂度:

T(n)=Θ(1)2T(n2)+Θ(n)n=1n>1

由主公式可得

T(n)=Θ(nlgn)

算法实现

//Copyright by ChestnutHeng.All rights reserved.
#include <iostream>
#define LEN 16
#define MAXNUM 60000
using namespace std;
typedef struct array_info_message  //储存子数组位置和加和的结构体
{
    int low;
    int high;
    int sum;
}array_info;
array_info max_crossed_array(int data[],int low,int mid,int high) //跨越了中点的数组求最大子数组
{
    int left_sum = -MAXNUM;
    int max_left;
    int sum = 0;
    for(int i = mid;i >= low; --i)  //遍历中点左半的和并计算最大值
    {

        sum += data[i];
        if(sum > left_sum)
        {
            left_sum = sum;
        }
        max_left = i;
    }
    int right_sum = -MAXNUM;
    int max_right;
    sum = 0;
    for(int i = mid + 1;i <= high; ++i) //遍历中点右半的和并计算最大
    {

        sum += data[i];
        if(sum > right_sum)
        {
            right_sum = sum;
        }
        max_right = i;
    }
    array_info answer = {max_left,max_right,left_sum + right_sum}; //求出本数组的最大和并返回
    return answer;

}

array_info max_child_array(int data[],int low,int high) //求解最大子数组
{
    int mid;
    if (high == low)  //递归终止条件
        {
            array_info bukket = {low,high,data[low]}; //当只有一个元素时返回它
            return bukket;
        }
    else  mid = (high + low)/2;   //分治
    array_info left_bukket = max_child_array(data,low,mid);
    array_info right_bukket = max_child_array(data,mid+1,high);
    array_info mid_bukket = max_crossed_array(data,low,mid,high);
    if(left_bukket.sum >= mid_bukket.sum && left_bukket.sum >= right_bukket.sum)
    {
        return left_bukket;
    }else if(right_bukket.sum >= mid_bukket.sum && right_bukket.sum >= left_bukket.sum)
    {
        return right_bukket;
    }else return mid_bukket; //找出最优的分治策略


}

int main(int argc, char const *argv[])
{
    int array[] = {13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7};
    cout << max_child_array(array,0,LEN-1).sum << endl;
    return 0;
}
点赞