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

来源:互联网 发布:windows mac地址 编辑:程序博客网 时间:2024/06/07 18:43

问题背景

输入:数天内的股价变化情况(+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 60000using 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;}
0 0
原创粉丝点击