如何提高算法的效率?

时间:2016-12-14 05:59:34

标签: algorithm optimization

我试图解决以下问题: 假设您有一个数组,其中第i个元素是第i天给定股票的价格。

如果您只被允许购买一股股票并卖出一股股票,请设计算法以找到买卖的最佳时机。

但我只能提出O(n^2)解决方案。当我看到它时,我理解了解决方案,但我无法想出O(n)解决方案。我可以获得一些优化算法的技巧吗?

4 个答案:

答案 0 :(得分:1)

我的解决方案是具有线性O(N)复杂度的算法。

您必须追踪以下索引信息

  • 最畅销的时间
  • 最佳购买时间
  • 最低价格时间
  • 最高利润

这个想法很简单。首先,设置最佳购买时间'迭代一个数组并改变最低价格时间'指数如果指数满足较低的股价。这是一个可以获得更高利润的潜在时机。

此外,当share [index] - share [min]之间的差异高于当前值时,更新最大利润。请记住“最低份额”'索引和'购买时间'完全不同。

c ++实现

pair<int, int> bestTradeTime(vector<int>& shares){
   int min = 0;
   int buy, sell, maxProfit=0;

   for(int i=1; i<n; i++){
      //If minimum price is found, update it. 
      //In this case, there is no way the profit is higher than maxProfit
      if(shares[min] > shares[i])
        min = i;

      //When finding maximum profit, update it. 
      else if(shares[i] - shares[min] > maxProfit){
        maxProfit = shares[i] - shares[min];
        buy = min;
        sell = i;
      }
   }
   return make_pair(buy, sell);
}

答案 1 :(得分:1)

与许多工艺品一样,这是经验问题,我想。在这种特殊情况下,对线性时间解决方案的良好暗示是寻找一些保持恒定数量的变量的算法,这些变量在扫描期间提供足够的信息来回答“从序列的开始到当前位置的问题”。 但即便如此,您还需要了解所寻找的信息类型。 “战略”方法是从问题的解决方案中寻求有用的信息:

1)你可以在线性时间内回答这个问题,如果你有一个最大利润数组,每个指数作为卖点(只需扫描最大值)。

2)如果在每个索引的子数组中有一个最小值数组,你可以计算每个卖点的最大利润。

3)在每个索引处结束的子阵列中携带最小值在线性时间内很容易。

答案 2 :(得分:0)

您可以使用线性 O(N)复杂度实现简单算法。 想象一下,你有一个价格数组,例如

   3 9 1 7 2 5 8 4 0

你必须在跟踪时扫描阵列

 - best buy index
 - best sell index
 - lowest price index

读取当前索引(i)和值(price),然后检查

 // do we have a lower price than ever?
 if (price < prices[lowest price index])
   lowest price index = i;

 // can we sell for a better price?
 if (price > prices[best sell index])
   best sell index = i;

 // shall we switch from the best buy index to the lowest price index?
 if (prices[best sell index] - prices[best buy index] < price - prices[lowest price index])
   best buy index = lowest price index;
   best sell index = i;  

C#实施:

private static Tuple<int, int> BestTimes(double[] prices) {
  int bestBuyIndex = 0;   // buy at the opening
  int bestSellIndex = 0;  // ...and sell it immediately (with profit 0)

  int lowestBuyIndex = 0;

  for (int i = 0; i < prices.Length; ++i) {
    double price = prices[i];

    if (price > prices[bestSellIndex])
      bestSellIndex = i;

    if (price < prices[lowestBuyIndex])
      lowestBuyIndex = i;

    if (price - prices[lowestBuyIndex] >= prices[bestSellIndex] - prices[bestBuyIndex]) {
      bestBuyIndex = lowestBuyIndex;
      bestSellIndex = i;
    }
  }

  return new Tuple<int, int>(bestBuyIndex, bestSellIndex);
}

测试:

double[] prices = new double[] { 3, 9, 1, 7, 2, 5, 8, 4, 0 };

Tuple<int, int> solution =  BestTimes(prices);

Console.Write($"Buy at {solution.Item1} (price {prices[solution.Item1]}) ");
Console.Write($"Sell at {solution.Item2} (price {prices[solution.Item2]}) ");

结果是

Buy at 2 (price 1) Sell at 6 (price 8)   

答案 3 :(得分:0)

我在接受采访时向我询问,并提出了以下逻辑:

我的想法是制作一个后缀数组,以获得优化的价格来卖出股票。 因此,如果我在price[i]买入股票,最佳解决方案是卖出股票

value = max(price[i+1], price[i+2], ... , price[n-1]);

因此,反向遍历数组我在price[(i+1) .. (n-1)]时间内找到O(n)的最大值。填充此数组后,我可以再向前遍历数组以计算最大利润并将其返回。此解决方案的复杂性为O(n)

这是我的C ++实现。

// Assuming the prices vector to be the prices of stock at different time
// instances. Also, I have assumed that we have to buy within values
// prices[0..(n-2)] and sell within values prices[1..(n-1)].

#include <iostream>
#include <algorithm>
#include <vector>

int max_profit(std::vector <int> prices) {
    int n = prices.size(), profit = 0, b = -1, s = -1;

    // sell[i] = the price at which you should sell when you buy the stock at
    // prices[i] = max(prices[(i+1)...(n-1)]);
    // position[i] = the position at which sell[i] is stored in prices[i].

    std::vector <int> sell (n-1), position (n-1);
    sell[n-2] = prices[n-1];
    position[n-2] = n-1;
    for(int i = n-3; i >= 0; i--) {
        if(sell[i+1] > prices[i+1]) {
            sell[i] = sell[i+1];
            position[i] = position[i+1];
        }
        else {
            sell[i] = prices[i+1];
            position[i] = i+1;
        }
    }

    for(int i = 0; i < n-1; i++) {
        if(sell[i+1] - prices[i] > profit) {
            profit = sell[i+1] - prices[i];
            b = i;
            s = position[i+1];
        }
    }
    std::cout << "Buy at position: " << b << std::endl;
    std::cout << "Sell at position: " << s << std::endl;
    return profit;
}

int main() {
    int profit = max_profit(std::vector <int> {3, 9, 1, 7, 2, 5, 8, 4, 0});
    std::cout << profit << std::endl;
    return 0;
}

令人遗憾的是,这个问题是在面试之前给我的,当面试开始时,我们甚至没有讨论这个解决方案。

这个问题的一个有趣的版本是以Buy Sell Buy Sell模式买卖两种不同的股票(我们不能做Buy Buy Sell Sell)并获得最大利润。