题目:
给你一个股价序列,告诉你每个时间点的股价,问你什么时候买什么时候卖获利最大。时间复杂度越低越好。
这是我在无意中看到的一个题目,突然来了一点兴致,想记录下来。
这个题目按照的逻辑需要注意的有几点:
1.问题简单话, 操作股票只能先买后卖
2.什么时候买什么时候卖获利最大,说明只允许一次买,只允许一次卖,最优的算法就是把最大的值找出来就好
算法:
input:一个序列 包含了24个小时,每个小时的股价
output:买的时间,卖的时间,转的差价
将这个序列排序后打到一个Dictionary<int,decimal>中
1.找到单价最小的时间 hourMinPrice,如果不是最后一个小时,继续找单价最大的时间hourMaxPrice,
如果hourMinPrice小于hourMaxPrice,直接计算差价并返回两个时间点
2.如果1没有返回的话,只能从0点开始遍历了,到23点结束
遍历每个时间点的时候,从时间比它大的那个范围里面选出股价最大的那个时间点
那遍历结束的时候,会得到 “每个小时买,哪个小时卖,这个小时买最多能赚多少钱 ” 这样的一个数据结构
类似于 List<model> model的变量是 buyHour,saleHour,benefit
从这个list中找到benefit最大的
--当然,题本只是要求找到最大收益的那个操作。可以直接return出来
model叫Policy
public class Policy
{
private int _buyHour;
private int _saleHour;
private decimal _benefit;
public int BuyHour
{
get { return this._buyHour; }
set { this._buyHour = value; }
}
public int SaleHour
{
get { return this._saleHour; }
set { this._saleHour = value; }
}
public decimal Benefit
{
get { return this._benefit; }
set { this._benefit = value; }
}
public Policy()
{
}
public Policy(int buyHour, int saleHour, decimal benefit)
{
this._buyHour = buyHour;
this._saleHour = saleHour;
this._benefit = benefit;
}
}
算法实现的方法叫GetMaxBenefit
public Policy GetMaxBenefit(string priceStr)
{
Policy policy=new Policy();
Dictionary<int,decimal> priceDic=new Dictionary<int, decimal>();
#region 初始化股价序列
string[] priceArray = priceStr.Trim().Split(',');
int index = 0;
foreach (var item in priceArray)
{
decimal price = 0.00m;
if (decimal.TryParse(item, out price))
{
priceDic.Add(index,price);
}
index++;
}
#endregion
KeyValuePair<int, decimal> minItem = priceDic.OrderBy(m => m.Value).First();
if (priceDic.Count<2)
{
return policy;
}
///1.找到单价最小的时间 hourMinPrice,如果不是最后一个小时,继续找单价最大的时间hourMaxPrice,
///如果hourMinPrice小于hourMaxPrice,直接计算差价并返回两个时间点
if (minItem.Key!=priceDic.Count-1)
{
KeyValuePair<int, decimal> maxItem = priceDic.OrderByDescending(m => m.Value).First();
if (minItem.Key<maxItem.Key)
{
policy=new Policy(minItem.Key,maxItem.Key,maxItem.Value-minItem.Value);
return policy;
}
}
//在遍历之前,先计算一下第一个时间点
KeyValuePair<int, decimal> first = priceDic.First();
Dictionary<int, decimal> noFirstDic =
priceDic.Where(m => m.Key > first.Key).ToDictionary(pair => pair.Key, pair => pair.Value);
KeyValuePair<int, decimal> max = noFirstDic.OrderByDescending(m => m.Value).First();
policy = new Policy(first.Key, max.Key, max.Value - first.Value);
//从第二个时间点开始遍历
for (int i = 1; i < priceDic.Count - 1; i++)
{
KeyValuePair<int, decimal> item = priceDic.ToArray()[i];
Dictionary<int, decimal> tempDic =
noFirstDic.Where(m => m.Key > item.Key).ToDictionary(pair => pair.Key, pair => pair.Value);
KeyValuePair<int, decimal> toCompare = tempDic.OrderByDescending(m => m.Value).First();
//如果一旦收入比基准大,就要赋值
if (toCompare.Value-item.Value>policy.Benefit)
{
policy = new Policy(item.Key, toCompare.Key, toCompare.Value - item.Value);
}
//对后续比较的序列进行收敛,因为是利用了linq的东西,性能也许不高,在这里能缩小范围就缩小一下
noFirstDic = tempDic;
}
return policy;
}
PS:其实这算法也就是算法,在真实的股票市场里面,谁也不能提前知道下个小时的股价
个人觉得顶多是用来估算过去的投资策略的,来环比当前最优的投资时间。