Chapter 4 --- The maximum-subarray problem (INTRODUCTION TO ALGORITHMS THIRD EDITION)

股票价格变动如下,什么时候买,什么时候卖,收益最大?
这里写图片描述

A brute-force solution

We can easily devise a brute-force solution to this problem: just try every possible
pair of buy and sell dates in which the buy date precedes the sell date.

#include<iostream>

using namespace std;

void brute_force(int a[],int len,int &buy,int &sell){
    a[0]=0;
    buy=0;//设定初值假定没有收益,则不购买
    sell=0;//设定初值假定没有收益,则不购买
    int sum=0;
    //第i-1天买,第j天卖,最大收益存到a[0]
    for(int i=1;i<len;i++){
        for(int j=i;j<len;j++){
            sum=0;
            for(int k=i;k<=j;k++){
                sum+=a[k];
            }
            if(sum>a[0]){
                a[0]=sum;
                buy=i-1;
                sell=j;
            }
        }
    }
}

int main()
{
    int a[17]={0,13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7};
    int buy,sell;
    brute_force(a,17,buy,sell);
    cout<<a[0]<<endl;
    cout<<"buy: "<<buy<<endl;
    cout<<"sell: "<<sell<<endl;
    return 0;
}

这里写图片描述

A transformation —– divide-and-conquer

这里写图片描述
If we treat this row as an array A, shown in Figure 4.3, we now want to find the nonempty, contiguous subarray of A whose values have the largest sum. We call this contiguous subarray the maximum subarray. If all the array entries were nonnegative, then the maximum-subarray problem would present no challenge, since the entire array would give the greatest sum.

这里写图片描述

As Figure 4.4(a) shows, any contiguous subarray A[i…j] of A[low…high] must lie in exactly one of the following places:

  • entirely in the subarray A[low…mid], so that low <= i <= j <= mid,
  • entirely in the subarray A[mid+1…high], so that mid < i<= j <= high,
  • crossing the midpoint, so that low <=i <= mid < j <=high.

In fact, a maximum subarray of A[low…high] must have the greatest sum over all subarrays entirely in A[low…mid], entirely in A[mid+1…high], or crossing the midpoint. We can find maximum subarrays of A[low…mid] and A[mid+1…high] recursively, because these two subproblems are smaller instances
of the problem of finding a maximum subarray.

这里写图片描述
这里写图片描述

#include<iostream>

using namespace std;

//存放购买股票的起始日期及获得的最大利润
struct result{
    int buy;
    int sell;
    int profit;
};

result find_max_cross_subarray(int a[],int l,int mid,int r){
    int l_max=-1000000;//假设这个值是无穷小
    int l_sum=0;
    int l_pos;
    for(int i=mid;i>=0;i--){
        l_sum+=a[i];
        if(l_sum>l_max){
            l_max=l_sum;
            l_pos=i;
        }
    }

    int r_max=-1000000;
    int r_sum=0;
    int r_pos;
    for(int i=mid+1;i<=r;i++){
        r_sum+=a[i];
        if(r_sum>r_max){
            r_max=r_sum;
            r_pos=i;
        }
    }

    result res;
    res.buy=l_pos-1;
    res.sell=r_pos;
    res.profit=l_max+r_max;
    return res;
}

//下面的递归分治,如果数组a仅有一个元素,可以直接判断收益是否小于等于0来决定购买与否
result find_max_subarray(int a[],int l,int r){
    if(l==r){
        result res;
        res.buy=l-1;
        res.sell=r;
        res.profit=a[l];
        return res;
    }
    else{
        int mid=(l+r)/2;
        result l_r=find_max_subarray(a,l,mid);
        result r_r=find_max_subarray(a,mid+1,r);
        result cross_r=find_max_cross_subarray(a,l,mid,r);
        if(l_r.profit>=r_r.profit && l_r.profit>=cross_r.profit){
            return l_r;
        }
        else if(r_r.profit>=l_r.profit && r_r.profit>=cross_r.profit){
            return r_r;
        }
        else{
            return cross_r;
        }
    }
}

int main()
{
    int a[17]={0,13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7};
    result res=find_max_subarray(a,1,16);
    cout<<res.profit<<endl;
    cout<<"buy: "<<res.buy<<endl;
    cout<<"sell: "<<res.sell<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/ccnuacmhdu/article/details/80931832