【亡羊补牢】挑战数据结构与算法 第71期 LeetCode 122. 买卖股票的最佳时机 II(DP&贪心)

    科技2023-09-28  80

    仰望星空的人,不应该被嘲笑

    题目描述

    给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。

    设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。

    注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

    示例 1:

    输入: [7,1,5,3,6,4] 输出: 7 解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。 随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3

    示例 2:

    输入: [1,2,3,4,5] 输出: 4 解释: 在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。 注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。 因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。

    示例 3:

    输入: [7,6,4,3,1] 输出: 0 解释: 在这种情况下, 没有交易完成, 所以最大利润为 0

    提示:

    1 <= prices.length <= 3 * 10 ^ 40 <= prices[i] <= 10 ^ 4

    来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    解题思路

    这道题想了挺久,参考了大佬的题解,典型的二维 dp 问题。

    状态 dp[i][j]表示:在下标为 i 的这一天,用户手上持股状态为 j 所获得的最大利润。

    说明:

    j 只有 2 个值:0 表示不持股(特指卖出股票以后的不持股状态),1 表示持股。「用户手上不持股」不代表用户一定在下标为 i 的这一天把股票抛售了;

    dp[i][0]怎样转移?

    对于当前这天,不持股份的话,当然可以是前一天也没有持股份,即 dp[i-1][0] 还有可能就是昨天持股了,我今天把这股份卖了,那么就要加上今天卖的那份股份值,即 dp[i-1][1] + prices[i]

    综上,得到状态方程:

    dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]);

    dp[i][1] 怎样转移?

    对于当前这天,如果持了股份的话,当天可以是前一天也持了股份,即 dp[i-1][1] 还有可能就是我今天才持股,同时注意,我们必须加上 dp[i-1][0],因为我们可以多笔交易,即从当前这天持股,那么买入带来的收益即为 dp[i-1][0]-prices[i]

    综上,得到状态方程:

    dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]); /** * @param {number[]} prices * @return {number} */ var maxProfit = function (prices) { let n = prices.length; if (n < 2) return 0; // 不足两天,肯定没收益 let dp = new Array(n); for (let i = 0; i < n; i++) { dp[i] = new Array(2); } dp[0][0] = 0; // 第一天不持股 dp[0][1] = -prices[0]; // 第一天持股,即买入 for (let i = 1; i < n; i++) { dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]); dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]); } return dp[n - 1][0]; // 最大收益,最后一天卖出股票的结果 };

    同时,这道题也可以用贪心来做,由于可以进行多次交易,那么只要价格上涨,我就买,不买我就亏了一个亿!

    /** * @param {number[]} prices * @return {number} */ var maxProfit = function (prices) { let res = 0; for (let i = 0; i < prices.length - 1; i++) { // 只要股票价格上涨,我就买,不然就亏! if (prices[i + 1] > prices[i]) { res += prices[i + 1] - prices[i]; } } return res; };

    最后

    文章产出不易,还望各位小伙伴们支持一波!

    往期精选:

    小狮子前端の笔记仓库

    leetcode-javascript:LeetCode 力扣的 JavaScript 解题仓库,前端刷题路线(思维导图)

    小伙伴们可以在Issues中提交自己的解题代码,🤝 欢迎Contributing,可打卡刷题,Give a ⭐️ if this project helped you!

    访问超逸の博客,方便小伙伴阅读玩耍~

    学如逆水行舟,不进则退 一百个Chocolate 认证博客专家 博客专家 博客之星 前端开发攻城狮 掘金搜【一百个Chocolate】座右铭:学如逆水行舟,不进则退!公众号:小狮子前端 期待小狮子们的加入~
    Processed: 0.013, SQL: 8