zoukankan      html  css  js  c++  java
  • [LeetCode 123] 买入与卖出股票的最佳时机III(Best Time to Buy and Sell Stock III)

    问题

    假设你有一个数组,其中的第i个元素表示一只股票在第i天的价格。

    设计一个算法找出最大的利润值。你最多只能进行两次交易。

    注意:

    你不能在同一时间进行多次交易(即你必须在再次买入股票之前卖出当前的股票)

    初始思路

    我们先来考虑只能进行一次交易的情况,即只能买入并卖出一次。可以尝试在第一天就买入股票,然后按顺序计算后面每一天卖出股票后的利润。将该利润和一个保存最大利润的变量比较,如果更大就更新最大利润。很显然,第一天就买入并在利润最大时卖出肯定不会是所有情况的答案,因为股票的价格是会下跌的。那么在什么情况下我们考虑尝试改变买入的时间呢?和第一天买入的价格相比,后面的价格无非就分两种情况:

    • 价格更高。这种情况显然是不可能出现优于第一天买入的利润的。因为[从这天之后第一天买入可能的最高利润]=[第一天到该天的利润]+[该天买入可能的最高利润]。所以这种情况下我们需要维持第一天买入的选择。
    • 价格一样或更低。[从这天之后第一天买入可能的最高利润]=[该天买入可能的最高利润]- [第一天到该天的亏损]。这种情况下在该天买入就有可能创造最高利润了。

    如此一来我们就可以得到一个O(n)的算法:

    设置买入价为第一天的价格

    从第二天价格遍历存放价格的数组

        如果该天卖出利润 > 0

            如果利润大于当前最大利润,更新最大利润

        如果该天卖出利润 <= 0

            设置买入价为该天价格

    现在让我们考虑两次交易的情况。因为不能在没卖出股票的情况下再次买入,所以两次买入卖出的区间是不能交叉的。那么我们可以在用上述方法找到一个新的最大利润后,从下一天开始用同样方法再找一次最大利润。将两个利润相加后尝试更新一个总的最大利润。注意处理完后外层的遍历不能中断,还要继续查找直到遍历完毕。伪代码变化如下:

    计算利润

    设置买入价为第一天的价格

    从第二天价格遍历存放价格的数组

        如果该天卖出利润 > 0

            如果利润大于当前最大利润,更新最大利润

               如果是在外层函数

                   第二次利润 = 计算利润(当前天数+1作为第一天)

                  如果利润+第二次利润大于总最大利润,更新总最大利润

        如果该天卖出利润 <= 0

            设置买入价为该天价格

    如果是在外层函数,返回总最大利润

    否则返回当前最大利润 

    转换成C++代码后如下:

     1 class Solution {
     2     public:
     3         int maxProfit(std::vector<int> &prices)
     4         {
     5             return CaculateProfit(prices, 0, FIRST).profit;
     6         }
     7         
     8     private:
     9         struct Profit
    10         {
    11             Profit() : profit(0), buyPrice(-1), buyDay(0), sellDay(0)
    12             {
    13             }
    14             
    15             int profit;
    16             int buyPrice;
    17             int buyDay;
    18             int sellDay;
    19         };
    20         
    21         enum Transaction
    22         {
    23             FIRST,
    24             SECOND
    25         };
    26         
    27         Profit CaculateProfit(std::vector<int> &prices, int start, Transaction transaction )
    28         {
    29             Profit currentProfit;
    30             Profit maxProfit;
    31             Profit secondProfit;
    32             Profit totalProfit;
    33             
    34             for(int day = start; day < prices.size(); ++day)
    35             {
    36                 if(currentProfit.buyPrice == -1)
    37                 {
    38                     currentProfit.buyPrice = prices[day];
    39                     currentProfit.buyDay = day;
    40                     continue;
    41                 }
    42                 
    43                 currentProfit.profit = prices[day] - currentProfit.buyPrice;
    44                 currentProfit.sellDay = day;
    45                 
    46                 if(currentProfit.profit < 0)
    47                 {
    48                     currentProfit.buyPrice = prices[day];
    49                     currentProfit.buyDay = day;
    50                     currentProfit.profit = 0;
    51                 }
    52                 
    53                 if(currentProfit.profit > maxProfit.profit)
    54                 {
    55                     if(transaction == FIRST)
    56                     {
    57                         secondProfit = CaculateProfit(prices, day + 1, SECOND);
    58                         
    59                         
    60                         if(currentProfit.profit + secondProfit.profit > totalProfit.profit)
    61                         {
    62                             totalProfit.profit = currentProfit.profit + secondProfit.profit;
    63                         }
    64                     }
    65 
    66                     maxProfit = currentProfit;
    67                 }
    68             }
    69             
    70             if(transaction == FIRST)
    71             {
    72                 return totalProfit;
    73             }
    74             else
    75             {
    76                 return maxProfit;
    77             }
    78         }
    79     };
    maxProfit

    提交后顺利通过Judge Large。

  • 相关阅读:
    软件工程 团队开发(2)
    软件工程 团队开发(1)
    大道至简阅读笔记01
    小工具集合用户模板和用户场景
    人月神话阅读笔记03
    人月神话阅读笔记02
    本周java学习
    本周学习总结
    本周java 学习进度报告
    《构建之法》读后感
  • 原文地址:https://www.cnblogs.com/shawnhue/p/leetcode_123.html
Copyright © 2011-2022 走看看