最长的盈利交易算法

时间:2014-12-18 16:57:34

标签: java algorithm

在采访中得到了这个问题。想知道是否有更好的解决方案:

鉴于股票的价格序列为[p1,p2,p3,p4,....对-N。交易员乔被要求在时间i买入1股股票,并在时间j卖出相同的股票。他的目标是最大化购买时间和销售时间之间的时间差距,但仍然有利可图。 例如,Trade Joe按时间顺序获得一系列价格:

  

时间,价格

     

10:00,10.3

     

10:01,10.1

     

10:02,11

     

10:03,13

     

10:04,9.5

     

10:05,7.3

     

10:06,8

     

10:07,10.2

     

10:08,9.8

如果他在10:01买入股票,价格= 10.1,并在10:07卖出,价格为10.2。他将获利0.1,买卖之间的时间为6分钟。这是这个例子的最长时间。

输入

第一行包含序列N的长度。接下来的N行包含(时间,价格)对: ñ 时间1,价格1 时间2,price2 ...

输出

使用给定的价格序列进行有利可图的买入 - 买出 - 卖出行动之间的最长时间

示例输入(使用文件或标准输入):

  

7

     

10:01,7

     

10:02,4

     

10:03,5

     

10:04,10

     

10:05,5

     

10:06,2

     

10:07,6

示例输出:

  

5(这是在10:02($ 4)使用买入,在10:07($ 6)卖出,   时间差是10:07 - 10:02 = 5分钟)

我提出的解决方案是O(N 2 ),只有一个小优化:

    for(int i = 0; i < lines.size(); i++){
        for(int j = lines.size()-1; j >= 0; j--){
            try
            {
                String[] partsFirst = lines.get(i).split(",");
                String[] partsLast = lines.get(j).split(",");

                String firstPriceString = partsFirst[1];
                String lastPriceString = partsLast[1];

                String firstDateString = partsFirst[0];
                String lastDateString = partsLast[0];

                double firstPriceInt = Double.parseDouble(firstPriceString);
                double lastPriceInt = Double.parseDouble(lastPriceString);


                Date date1 = format.parse(firstDateString);
                Date date2 = format.parse(lastDateString);
                long difference = date2.getTime() - date1.getTime();

                //optimization
                if(difference <= maxDuration)
                    continue;


                if(lastPriceInt > firstPriceInt && (difference) > maxDuration)
                    maxDuration = difference;
            }
            catch (ParseException ex)
            {
                System.out.println("Exception "+ex);
            }
        }
    }

那里有更有效的解决方案吗?

2 个答案:

答案 0 :(得分:4)

是的,有一个O(n)时间算法。

向前扫描价格(从头到尾),在辅助阵列中存储价格低于以前所有价格的价格,以及他们的时间。做类似的事情,发现所有价格都高于所有后续价格。这些数组都是自然排序的。

最优交易从第一个阵列购买并卖出到第二个。两个数组的变量排序合并将识别所有可盈利的O(n)交易,并且鉴于一个端点是固定的,最大距离。

合并的方式是我们将索引初始化为“买入”(第一个)数组,将另一个索引初始化为“卖出”(第二个)数组,从最低价格开始。如果当前买入价格低于当前卖出价格,则考虑该交易并继续下一个最高买入价格。否则,继续下一个最高卖价。

答案 1 :(得分:2)

以下是对David Eisenstat's Answer中提到的O(n)解决方案的解释。

这里的主要观察是,如果A点的时间比另一点B的价格低,那么A是比B更好的买点。例如,如果你有价格[2,3,4] ,1,...](按时间排序),如果您已经测试过,那么测试3和4作为购买点是没有意义的。我们可以得出结论,对于起点,我们只需要测试价格小于之前的所有价格。这可以通过扫描价格并保存符合该条件的点来完成。

这会给我们一个数组buy_points = [p 1 ,p 2 ,p 3 ,...]

第二个观察结果是,对于任何卖点,如果它的价格不高于买入点p i ,那么它不会高于任何先前的点数p j ,其中j <一世。这是因为购买点中的每个元素都小于之前的所有点。

鉴于这些观察结果,我们可以按如下方式构建算法:

我们向后扫描买​​点阵列和卖点阵列(原价格阵列)。对于每对售价和购买价格:

  1. 如果售价较高,那么这是一个有效的交易,我们应该检查它是否比我们目前最好的交易更好。我们也转到上一个购买点,因为这是我们能够获得的最佳结果。
  2. 如果售价较低,我们可以跳过这一点,因为它不会与之前的任何购买点一起使用。
  3. 这是python中的示例代码:

    def get_max_distance(prices):
        min_price_so_far = None
        buying_points = []
        for time, price in prices:
           if min_price_so_far is None or price < min_price_so_far[1]:
               min_price_so_far = (time, price)
               buying_points.append(min_price_so_far)
    
        selling_points = reversed(prices)
        buying_points = reversed(buying_points)
    
        buying_point = next(buying_points, None)
        selling_point = next(selling_points, None)
        best = 0
        while buying_point and selling_point:
            buying_time, buying_price  = buying_point
            selling_time, selling_price = selling_point
            if selling_price > buying_price:
                if selling_time > buying_time:
                    best = max(best, selling_time - buying_time)
                buying_point = next(buying_points, None)
            else:
                selling_point = next(selling_points, None)
        return best