股市买入卖出时间点选择问题

题目:

给你一个股价序列,告诉你每个时间点的股价,问你什么时候买什么时候卖获利最大。时间复杂度越低越好。


这是我在无意中看到的一个题目,突然来了一点兴致,想记录下来。

这个题目按照的逻辑需要注意的有几点:

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:其实这算法也就是算法,在真实的股票市场里面,谁也不能提前知道下个小时的股价

个人觉得顶多是用来估算过去的投资策略的,来环比当前最优的投资时间。






评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值