【代码随想录】动态规划专题3(Python)

文章介绍了多个使用动态规划解决的股票交易问题,包括不同限制条件下的最佳买卖时机,如打家劫舍系列(考虑是否抢劫相邻房屋)和买卖股票系列(考虑手续费、冷冻期等)。每个问题都通过状态转移方程展示了如何计算最大利润。
摘要由CSDN通过智能技术生成

17.打家劫舍

198.打家劫舍
dp[i]表示第i家能获得的最高金额
dp[i] = max(dp[i-1], dp[i-2]+nums[i])
dp[0] = nums[0], dp[1] = max(nums[0], nums[1])

class Solution:
    def rob(self, nums: List[int]) -> int:
        if len(nums) == 0:  # 如果没有房屋,返回0
            return 0
        if len(nums) == 1:  # 如果只有一个房屋,返回其金额
            return nums[0]
        dp = [0]*len(nums)
        dp[0] = nums[0]
        dp[1] = max(nums[0], nums[1])
        for i in range(2,len(nums)):
            dp[i] = max(dp[i-1], dp[i-2]+nums[i])
        return dp[-1]

18.打家劫舍II

213.打家劫舍II
围成环,即不带第一个和不带最后一个两种情况的最大值

class Solution:
    def dprob(self, nums: List[int]) -> int:
        if len(nums)==0: return 0
        if len(nums)==1: return nums[0]
        dp = [0]*len(nums)
        dp[0] = nums[0]
        dp[1] = max(nums[0],nums[1])
        for i in range(2,len(nums)):
            dp[i] = max(dp[i-1],dp[i-2]+nums[i])
        return dp[-1]
    def rob(self, nums: List[int]) -> int:
        if len(nums)==0: return 0
        if len(nums)==1: return nums[0]
        r0 = self.dprob(nums[:-1])
        r1 = self.dprob(nums[1:])
        return max(r0,r1)

19.打家劫舍 III

337.打家劫舍 III
后序遍历,每个节点分为偷与不偷
不偷:max(左不偷,左偷)+(右不偷,右偷)
偷:左不偷+右不偷+自身值

class Solution:
    def traversal(self, root: TreeNode) -> int:
        if not root: return (0,0)
        left = self.traversal(root.left)
        right = self.traversal(root.right)
        return (max(left)+max(right),left[0]+right[0]+root.val)
    def rob(self, root: Optional[TreeNode]) -> int:
        return max(self.traversal(root))

20.买卖股票的最佳时机

121. 买卖股票的最佳时机
dp[i][0]持有,dp[i][1]不持有
dp[i][0]=max(之前持有,买了)=max(dp[i-1][0],-price[i])
dp[i][1]=max(之前不持有,卖了)=max(dp[i-1][1],dp[i-1][0]+price[i])
dp[0][0]=-price[0],dp[0][1]=0

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        dp = [[0]*2 for _ in range(len(prices))]
        dp[0][0] = -prices[0]
        for i in range(1,len(prices)):
            dp[i][0] = max(dp[i-1][0],-prices[i])
            dp[i][1] = max(dp[i-1][1],dp[i-1][0]+prices[i])
        return dp[-1][1]

21.买卖股票的最佳时机II

122.买卖股票的最佳时机II
与20的区别:dp[i][0]=max(之前持有,买了)=max(dp[i-1][0],dp[i-1][1]-price[i])

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        dp = [[0]*2 for _ in range(len(prices))]
        dp[0][0] = -prices[0]
        for i in range(1,len(prices)):
            dp[i][0] = max(dp[i-1][0],dp[i-1][1]-prices[i])
            dp[i][1] = max(dp[i-1][1],dp[i-1][0]+prices[i])
        return dp[-1][1]

22.买卖股票的最佳时机III

123.买卖股票的最佳时机III
dp[i]的定义:
dp[i][0]不操作;dp[i][1]第一次持有;dp[i][2]第一次不持有;dp[i][3]第二次持有;dp[i][4]第二次不持有
递推公式:
dp[i][0] = dp[i-1][0]
dp[i][1] = max(之前第一次持有dp[i-1][1],第一次买入dp[i-1][0]-prices[i])
dp[i][2] = max(dp[i-1][2],dp[i-1][1]+prices[i])
dp[i][3] = max(dp[i-1][3],dp[i-1][2]-prices[i])
dp[i][4] = max(dp[i-1][4],dp[i-1][3]+prices[i])
初始化:
dp[0][0]=0
dp[0][1]=-prices[0]
dp[0][2]=0
dp[0][3]=-prices[0]
dp[0][4]=0

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        dp = [[0]*5 for _ in range(len(prices))]
        dp[0][0]=0
        dp[0][1]=-prices[0]
        dp[0][2]=0
        dp[0][3]=-prices[0]
        dp[0][4]=0
        for i in range(1,len(prices)):
            dp[i][0] = dp[i-1][0]
            dp[i][1] = max(dp[i-1][1],dp[i-1][0]-prices[i])
            dp[i][2] = max(dp[i-1][2],dp[i-1][1]+prices[i])
            dp[i][3] = max(dp[i-1][3],dp[i-1][2]-prices[i])
            dp[i][4] = max(dp[i-1][4],dp[i-1][3]+prices[i])
        return dp[-1][4]

22.买卖股票的最佳时机IV

188.买卖股票的最佳时机IV
最多k次,即把21中的2换成对应的k

class Solution:
    def maxProfit(self, k: int, prices: List[int]) -> int:
        dp = [[0]*(2*k+1) for _ in range(len(prices))]
        dp[0][0]=0
        for i in range(1,k+1):
            dp[0][2*i-1] = -prices[0]
            dp[0][2*i] = 0
        for i in range(1,len(prices)):
            dp[i][0] = dp[i-1][0]
            for j in range(1,k+1):
                dp[i][2*j-1] = max(dp[i-1][2*j-1],dp[i-1][2*j-2]-prices[i])
                dp[i][2*j] = max(dp[i-1][2*j],dp[i-1][2*j-1]+prices[i])
        return dp[-1][-1]

23.最佳买卖股票时机含冷冻期

309.最佳买卖股票时机含冷冻期
dp[i][0]持有,之前就持有、冷冻期第二天买入、不持有期买入;
dp[i][1]卖出当天,持有期卖了;
dp[i][2]冷冻期,卖出第二天;
dp[i][3]不持有,冷冻期第二天、之前就不持有

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        dp = [[0]*4 for _ in range(len(prices))]
        dp[0][0] = -prices[0]
        for i in range(1,len(prices)):
            dp[i][0] = max(dp[i-1][0],dp[i-1][2]-prices[i],dp[i-1][3]-prices[i])
            dp[i][1] = dp[i-1][0]+prices[i]
            dp[i][2] = dp[i-1][1]
            dp[i][3] = max(dp[i-1][3],dp[i-1][2])
        return max(dp[-1])

24.买卖股票的最佳时机含手续费

714.买卖股票的最佳时机含手续费
和21相比,卖出的时候多花手续费

class Solution:
    def maxProfit(self, prices: List[int], fee: int) -> int:
        dp = [[0]*2 for _ in range(len(prices))]
        dp[0][0] = -prices[0]
        for i in range(1,len(prices)):
            dp[i][0] = max(dp[i-1][0],dp[i-1][1]-prices[i])
            dp[i][1] = max(dp[i-1][1],dp[i-1][0]+prices[i]-fee)
        return dp[-1][1]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值