问题描述
假定你获得了投资挥发性化学公司的机会。与其他公司一样,该公司的股票价格是不稳定的。你被准许可以在某个时刻买进一股该公司的股票,并在之后的某个时期将其卖出。
你可以了解股票将来的价格,使得自己的利益最大化。你的任务是根据每天的股票价格,求得最大的收益。
输入
一个整数n,表示天数
接下来一行,n个整数,用空格隔开,表示每天的股价。
输出
一个整数,表示最大收益。
问题分析
这类问题就是典型的最大子数组问题,可以通过将后一天的股票值减去前一天的股票值,即可得到这两天买入售出所盈利(亏损)的值。
接着将这些各项存入数组中,在找数组中某一连续子数组为最大即可,即从该子数组第一天购买,该子数组最后一天售出,所得即为最大值。
于是可以想到利用分治算法,计算mid左侧数组中子数组的最大值,计算mid右侧数组中子数组的最大值,在计算包含mid段中的子数组的最大值
具体代码
#include<bits/stdc++.h>
#define maxn 1005000
using namespace std;
int a[maxn];
int max(int p, int q, int r){
if(p > q && p > r)
return p;
else if(q > p && q > r)
return q;
else if(r > p && r > q)
return r;
}
int get_max(int l, int r){
if(l == r)//分治到只剩一项
return a[l];
int left_max, right_max, mid_max;
int mid_max_l = -maxn, mid_max_r = -maxn, sum = 0;
int mid = (l + r) >> 1;
left_max = get_max(l, mid);
right_max = get_max(mid + 1, r);
//分治得到left_max和right_max
for(int i = mid; i >= l; i--){//求出mid及左侧的最大子段和
sum += a[i];
if(sum > mid_max_l)
mid_max_l = sum;
}
sum = 0;//清零
for(int i = mid + 1; i <= r; i++){//求出mid右侧的最大子段和
sum += a[i];
if(sum > mid_max_r)
mid_max_r = sum;
}
mid_max = mid_max_l + mid_max_r;
return max(left_max, right_max, mid_max);
}
int main()
{
int n, m;
cin >> n;
for(int i = 0; i <= n; i++)
cin >> a[i];
for(int i = 1; i < n; i++)//处理数据
a[i] = a[i + 1] - a[i];
m = get_max(1, n - 1);
cout << m;
return 0;
}
总结
转化成求最大子数组问题后,采用分治方法解决。