zoukankan      html  css  js  c++  java
  • [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 题目总结

  • 相关阅读:
    POJ1486 Sorting Slides 二分图or贪心
    POJ2060 Taxi Cab Scheme 最小路径覆盖
    POJ3083 Children of the Candy Corn 解题报告
    以前的文章
    POJ2449 Remmarguts' Date K短路经典题
    这一年的acm路
    POJ3014 Asteroids 最小点覆盖
    POJ2594 Treasure Exploration 最小路径覆盖
    POJ3009 Curling 2.0 解题报告
    POJ2226 Muddy Fields 最小点集覆盖
  • 原文地址:https://www.cnblogs.com/cnoodle/p/13698513.html
Copyright © 2011-2022 走看看