• [LeetCode] 123. Best Time to Buy and Sell Stock III


    Say you have an array for which the ith element is the price of a given stock on day i.

    Design an algorithm to find the maximum profit. You may complete at most two transactions.

    Note: You may not engage in multiple transactions at the same time (i.e., you must sell the stock before you buy again).

    Example 1:

    Input: prices = [3,3,5,0,0,3,1,4]
    Output: 6
    Explanation: Buy on day 4 (price = 0) and sell on day 6 (price = 3), 
    profit = 3-0 = 3. Then buy on day 7 (price = 1) and sell on day
    8 (price = 4), profit = 4-1 = 3.

    Example 2:

    Input: prices = [1,2,3,4,5]
    Output: 4
    Explanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), 
    profit = 5-1 = 4. Note that you cannot buy on day 1, buy on day 2 and
    sell them later, as you are engaging
    multiple transactions at the same time. You must sell before buying again.

    Example 3:

    Input: prices = [7,6,4,3,1]
    Output: 0
    Explanation: In this case, no transaction is done, i.e. max profit = 0.
    

    Example 4:

    Input: prices = [1]
    Output: 0

    Constraints:

    • 1 <= prices.length <= 105
    • 0 <= prices[i] <= 105

    买卖股票的最佳时机III。题意跟之前两个版本类似,也是给一个数组,表示每天的股价。这道题给的题设是如果允许你最多买卖两次,请你返回最大利润。

    思路依然是动态规划。这道题我还是参考了一个写的非常好的题解。这里我们依然需要一个二维数组dp[][]。其中第一维的长度是数组的长度len,第二维的长度是5,这里只有可能是五个数字0,1,2,3,4。这里第一维代表的就是遍历到某个位置的DP值,第二维表示的是在当前位置是否持有股票。注意这里的不持有不是一直不买,而是卖出之后的不持有。五个数字的定义如下,

    • 0 - 没有任何交易的时候
    • 1 - 第一次买
    • 2 - 第一次卖
    • 3 - 第二次买
    • 4 - 第二次卖

    根据这个定义,我们能得出几个结论,

    所有的dp[i][3]都需要定义成Integer.MIN_VALUE。因为第一次买入都没发生的时候,第二次的买入就更加无从谈起

    所有的dp[i][0]都是0,因为没有交易就不会有收益

    最后的收益只有可能是从第一次卖或者第二次卖之后得到的,因为不卖出就没有收益

    时间O(n)

    空间O(mn) - 二维数组

    Java实现

     1 class Solution {
     2     public int maxProfit(int[] prices) {
     3         int len = prices.length;
     4         // corner case
     5         if (len < 2) {
     6             return 0;
     7         }
     8         // dp[i][j] ,表示 [0, i] 区间里,状态为 j 的最大收益
     9         // j = 0:什么都不操作
    10         // j = 1:第 1 次买入一支股票
    11         // j = 2:第 1 次卖出一支股票
    12         // j = 3:第 2 次买入一支股票
    13         // j = 4:第 2 次卖出一支股票
    14         // 初始化
    15         int[][] dp = new int[len][5];
    16         dp[0][0] = 0;
    17         dp[0][1] = -prices[0];
    18         // 3 状态都还没有发生,因此应该赋值为一个不可能的数
    19         for (int i = 0; i < len; i++) {
    20             dp[i][3] = Integer.MIN_VALUE;
    21         }
    22         // 状态转移只有 2 种情况:
    23         // 情况 1:什么都不做
    24         // 情况 2:由上一个状态转移过来
    25         for (int i = 1; i < len; i++) {
    26             // j = 0 的值永远是 0
    27             dp[i][0] = 0;
    28             dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
    29             dp[i][2] = Math.max(dp[i - 1][2], dp[i - 1][1] + prices[i]);
    30             dp[i][3] = Math.max(dp[i - 1][3], dp[i - 1][2] - prices[i]);
    31             dp[i][4] = Math.max(dp[i - 1][4], dp[i - 1][3] + prices[i]);
    32         }
    33         // 最大值只发生在不持股的时候,因此来源有 3 个:j = 0 ,j = 2, j = 4
    34         return Math.max(0, Math.max(dp[len - 1][2], dp[len - 1][4]));
    35     }
    36 }

    LeetCode 题目总结

  • 相关阅读:
    数字排列问题
    【动态规划】合唱团
    【动态规划】多米诺骨
    【动态规划】抄近路
    【动态规划】拦截导弹
    【动态规划】能量项链
    【动态规划】skiing
    [原创]Devexpress XtraReports 系列 3 创建主从报表
    [原创]Devexpress XtraReports 系列 2 创建表格报表
    [原创]Devexpress XtraReports 系列 1 创建静态报表
  • 原文地址:https://www.cnblogs.com/cnoodle/p/13698513.html
Copyright © 2020-2023  润新知