• leetcode(力扣) 188. 买卖股票的最佳时机 IV (动态规划)


    题目描述

    给定一个整数数组 prices ,它的第 i 个元素 prices[i] 是一支给定的股票在第 i 天的价格。
    设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。
    注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

    示例 1:
    输入:k = 2, prices = [2,4,1]
    输出:2
    解释:在第 1 天 (股票价格 = 2) 的时候买入,在第 2 天 (股票
    价格 = 4) 的时候卖出,这笔交易所能获得利润 = 4-2 = 2 。

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

    思路分析

    这道题的前置三个题

    上一个123题是只能交易2次,这个题是交易k次,k由题目给出。
    其实可以从上一题的k=2中找到规律,写出k次的代码。

    老规矩 五步走:

    1.确定dp数组含义:

    dp[i][j] :第i天的状态为j,所剩下的最大现金是dp[i][j]

    这道题的状态 和上一道题是一样的:

    0 表示不操作
    1 第一次买入
    2 第一次卖出
    3 第二次买入
    4 第二次卖出



    规律其实也很好发现,除了0以外,偶数卖出,奇数买入。

    2.状态转移公式;

    回顾一下上一道题的公式:

    dp[i][1]第i天持有股票 手里的最大金额:
    要么是前几天买入的,今天还没卖,所以是持有状态,继承前一天的持有状态就行了。要么是今天刚买入的,则就是前一天无操作时的状态再花掉今天要买股票的钱。
    所以就是:dp[i][1] = max(dp[i-1][1],dp[i-1][0]-prices[i])


    dp[i][2] 第i天不持有股票 手里最大的金额:
    要么是前几天就已经卖掉了,现在还是不持有状态,则继承前一天不持有状态。要么是今天刚卖掉,所以是前一天持有状态,再加上今天要卖掉的钱。
    所以就是: dp[i][2] = max(dp[i-1][2],dp[i-1][1]+prices[i])

    		# dp[i][1]第i天持有股票 手里的最大金额
            dp[i][1] = max(dp[i-1][1],dp[i-1][0]-prices[i])
            # dp[i][2] 第i天不持有股票 手里最大的金额
            dp[i][2] = max(dp[i-1][2],dp[i-1][1]+prices[i])
            # dp[i][3] 第i天第二次持有股票 手里最大的金额
            dp[i][3] = max(dp[i-1][3],dp[i-1][2]-prices[i])
            # dp[i][4] 第i天第二次不持有股票 手里最大的金额
            dp[i][4] = max(dp[i-1][4],dp[i-1][3]+prices[i])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    继续从2次中找规律。

    k次的时候:

    手中持有股票状态。
    dp[i][j+1] = max(dp[i-1][j+1],dp[i-1][j]-prices[i])

    手中不持有股票状态。
    dp[i][j+2] = max(dp[i-1][j+2],dp[i-1][j+1]+prices[i])

    3.初始化dp数组:

    继续从2次中找规律,每次买入的时候都是-prices[0],卖的时候都是0.

    所以k次中:

    dp[0][j] j为奇数的时候 就是买入状态 初始化成 -prices[0]。

    4.遍历顺序:
    没得说,从前往后

    最后的返回值 :
    2次的时候 返回的是 dp[-1][4],
    k次就返回 dp[-1][2*k]

    5.模拟dp数组的值:
    debug用,直接略了,有问题再回来。

    完整代码

    class Solution:
        def maxProfit(self, k: int, prices: List[int]) -> int:
            dp = [[0 for i in range(2*k+1)] for j in range(len(prices))]
            if len(prices) == 0:
                return 0
            for i in range(1,2*k,2):
                dp[0][i] = -prices[0]
                
            for i in range(1,len(prices)):
                for j in range(0,2*k,2):
                    dp[i][j+1] = max(dp[i-1][j+1],dp[i-1][j]-prices[i])
                    dp[i][j+2] = max(dp[i-1][j+2],dp[i-1][j+1]+prices[i])
            return dp[-1][2*k]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  • 相关阅读:
    【前端每日基础】day34——HTTP和HTTPS
    MyBatis——【第三章】管理关系映射及spring集成
    10.10作业
    Docker Compose学习笔记
    手把手教你使用 Spring Boot 3 开发上线一个前后端分离的生产级系统(六) - 本地缓存 Caffeine 和 分布式缓存 Redis 集成与配置
    UNIAPP day_01(8.30) uin-app概述
    Linux下的一些工具
    【记录】软件自动修复工具Jaid配置、调试、运行及相关问题的解决方案
    推荐一个AI人工智能技术网站(一键收藏,应有尽有)
    MIT6.S081的gdb调试方法
  • 原文地址:https://blog.csdn.net/qq_38737428/article/details/127677363