分治算法——最大子数组

1. 背景
假设你知道未来一段时间内股票的涨跌情况(是开天眼了吗),怎样投资才能获利最大呢?最直接想到,在最低点买入,在最高点卖出。可实际情况(知到未来就不实际)并总能满足,例如最高价格出现在最低价格之前(逆转时间不行吗)。聪明的人又想到新的方法,如果最低价格出现最高价格的后面。则找到最高价格前的最低价格,计算其差值。再找到最低价格后的最高价格,计算其差值。两差值比较取大值。但此方法仍不能保证结果的正确性。

2.算法提出
将每一天相对于前一天的变化值计算出,增加为正数,减少为负数。将这些变化值按照时间顺序填入数组中。则最大收益就是数组中子数组的最大值。也就是最大子数组的求解。
在求解最大子数组时有暴力遍历算法,即求出每个子数组的值,取最大的子数组。这样当数组足够大时,非常耗时。所以我们将采取分治算法去求最大子数组的问题。分治算法在之前提到过,不再赘述,直接对分治算法在求最大子数组的应用加以描述。
首先,分解,将问题分解为较小的子问题。取数组的中间位置,可以知道最大子数组的位置有三。一在中间位置的左边,二在中间位置的右边,三跨过了中间位置。第一种和第二种情况可以看成是求左边子数组的最大子数组,可以进行递归。当只有一个元素时,可以求解。而第三种情况的求解不通过递归,而是可以直接求解。因为必须经过中间元素,并且子数组连续。以中间元素为起点向两边延申求得最大值。当数组被分解为都是单因素的子数组时便可以递归返回,进行合并。

3.代码实现

#include 
#include 

//该结构体储存着子数组的信息
typedef struct data{
   
    int start;//子数组在数组中的起始位置
    int end;//子数组在数组中的结束位置
    int sum;//子数组的元素求和的值
}data;

//该函数寻找最大的跨过中间元素的子数组
data* find_max_crossing_subarray(int* A,int low,int mid,int high){
   
    int left_sum=INT_MIN;
    int right_sum=INT_MIN;
    int max_left,max_right;
    int i,j,sum;
    data* result;
    for(i=mid,sum=0;i>=low;i--)

你可能感兴趣的:(分治算法)