Leetcode第五天动态规划 (打家劫舍 股票抛售) python

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

213 打家劫舍 II
你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。

给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,今晚能够偷窃到的最高金额。

class Solution:
    def rob(self, nums: List[int]) -> int:
        #当偷窃的人家超过两家 则要考虑
        #考虑到情况1首位相连 当偷了第一家时,最后一家不能偷窃
        #情况2 当偷了最后一家时 第一家不能偷窃
        #dp[i] 表示第i次可以偷取的最高金额
        #dp[i] 递推公式dp[i]=max(dp[i-1],dp[i-2]+nums[i])
        if len(nums)<=2:
            return max(nums)
        else:
            nums_1=nums[0:-1]
            nums_2=nums[1:]
     
            dp_1=[0]*(len(nums_1))
            dp_1[0]=nums_1[0]
            dp_1[1]=max(nums_1[0],nums_1[1])

            dp_2=[0]*(len(nums_2))
            dp_2[0]=nums_2[0]
            dp_2[1]=max(nums_2[0],nums_2[1])
            
            for i in range(2,len(nums_1)):
                dp_1[i]=max(dp_1[i-1],dp_1[i-2]+nums_1[i])
                
            for j in range(2,len(nums_2)):
                dp_2[j]=max(dp_2[j-1],dp_2[j-2]+nums_2[j])
            
            return max(dp_1[-1],dp_2[-1])

337 打家劫舍III
小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为 root 。

除了 root 之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果 两个直接相连的房子在同一天晚上被打劫 ,房屋将自动报警。

给定二叉树的 root 。返回 在不触动警报的情况下 ,小偷能够盗取的最高金额 。
错误代码
我一开始想的是小偷只能偷某一层但是其实偷相邻层的同一边的孩子也不是直接相邻的,不会触发警报,思考错误

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def rob(self, root: Optional[TreeNode]) -> int:
        #dp[i] 为偷到第i层能窃取的最大金额
        #只能一层一层的偷
        #dp[i]=max(dp[i-1],dp[i-2]+sum(val))
        #遍历顺序 层次遍历
        dp=[0]*(100)
        dp[0]=root.val
        if not root.left and not root.right:
            return root.val
        que=[]
        sum_=0
        que.append(root.left)
        que.append(root.right)
        if root.left:
            sum_=sum_+root.left.val
        if root.right:
            sum_=sum_+root.right.val
        dp[1]=max(dp[0],sum_)
 
        for i in range(2,100):
            sum_=0
            flag=2**i
            
            #while(que)
            for j in range(0,flag):
                chi=que.pop(0)
                
                if chi:
                    que.append(chi.left)
                    que.append(chi.right)
                    if chi.left:
                        sum_=sum_+chi.left.val
                    if chi.right:
                        sum_=sum_+chi.right.val
                else:
                    que.append(TreeNode(0))
                    que.append(TreeNode(0))
            # print(sum_)
            dp[i]=max(dp[i-1],dp[i-2]+sum_)
            if que:
                break
        print(dp)
        return dp[i]

正确代码

        #dp[i][0] 不偷节点i可以得到的最大值金额
        #dp[i][1]表示偷该节点可以得到的最大值金额
        #通过后序遍历树可以满足递归关系 如果抢了该节点,其孩子就不要动
        #如果没有偷该节点,可以考虑一下偷取孩子节点的金额
        #递归关系 父母dp[i][0]=max(dp[left][1],dp[left][1])+max(dp[right][1],dp[right][1])
        #   dp[i][1]=父母节点的val+dp[left][0]+dp[right][0]
       
        def tree(cur):
            if not cur:
                return 0,0
            left_tou,left_no=tree(cur.left)
            right_tou,right_no=tree(cur.right)
            val1=cur.val+left_no+right_no
            val2=max(left_tou,left_no)+max(right_tou,right_no)
            return val1,val2
        return max(tree(root))

121 买卖股票
给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        #dp[i][0]表示第i天持有股票的最大现金 dp[i][0]表示第i天不持有股票的现金
        #递推关系 dp[i][0]=max(dp[i-1][0],-price[i])
        #dp[i][1]=max(dp[i-1][1],dp[i-1][0]+price[i])
        #初始化dp[0][0]=-price dp[0][1]=0
        dp=[[0]*2 for _ in range (len(prices))]
        dp[0][0]=-prices[0] 
        dp[0][1]=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]

122 买卖股票II
给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。

在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。返回 你能获得的 最大 利润 。

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
    
    #dp[i][0]表示第i天持有股票的最大现金 dp[i][0]表示第i天不持有股票的现金
    #递推关系 dp[i][0]=max(dp[i-1][0],dp[i-1][1]-price[i])
    #dp[i][1]=max(dp[i-1][1],dp[i-1][0]+price[i])
    #初始化dp[0][0]=-price dp[0][1]=0
        dp=[[0]*2 for _ in range (len(prices))]
        dp[0][0]=-prices[0] 
        dp[0][1]=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]

123. 买卖股票的最佳时机 III
给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。

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

    def maxProfit(self, prices: List[int]) -> int:
        #dp[i][0]表示不动作
        #dp[i][1]表示第i天第一次购入股票
        ##dp[i][2]表示第i天第一次抛出股票
        #dp[i][3]表示第i天第二次购入股票
        ##dp[i][4]表示第i天第二次抛出股票
        #递推关系 dp[i][0]=max(dp[i-1][0],dp[i-1][1]-price[i])
        #dp[i][1]=max(dp[i-1][1],dp[i-1][0]+price[i])
        #以此类推
        #初始化dp[0][0]=-price dp[0][1]=0
        dp=[[0]*5 for _ in range (len(prices))]
        dp[0][1]=-prices[0] 
        dp[0][3]=-prices[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][-1]

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

class Solution:
    def maxProfit(self, k: int, prices: List[int]) -> int:
        #dp[i][0]表示不动作
        #dp[i][1]表示第i天第一次购入股票
        ##dp[i][2]表示第i天第一次抛出股票
        #dp[i][3]表示第i天第二次购入股票
        ##dp[i][4]表示第i天第二次抛出股票
        #递推关系 dp[i][0]=max(dp[i-1][0],dp[i-1][1]-price[i])
        #dp[i][1]=max(dp[i-1][1],dp[i-1][0]+price[i])
        #以此类推
        #初始化dp[0][0]=-price dp[0][1]=0
        dp=[[0]*(1+k*2) for _ in range (len(prices))]
        for i in range(1+k*2):
            if i%2==1:
                dp[0][i]=-prices[0] 

        for i in range(1,len(prices)):
            dp[i][0]=dp[i-1][0]
            for j in range(1,k*2+1):
                if j %2==1:#第j次购入股票
                    dp[i][j]=max(dp[i-1][j],dp[i-1][j-1]-prices[i])
                else:#第j次抛出股票
                    dp[i][j]=max(dp[i-1][j],dp[i-1][j-1]+prices[i])
        # print(dp)
        return dp[-1][-1]

309. 最佳买卖股票时机含冷冻期
给定一个整数数组prices,其中第 prices[i] 表示第 i 天的股票价格 。​
设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):
卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

错误代码
class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        #dp[i][0]表示买入股票
        #dp[i][1]表示冷冻期渡过卖出股票,一直保持卖出状态
        #dp[i][2]表示今天卖出了股票
        #dp[i][3]表示冷冻期目前最大现金
        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],max(dp[i-1][1]-prices[i],dp[i-1][3]))
            dp[i][1]=max(dp[i-1][1],dp[i-1][3])
            dp[i][2]=dp[i-1][0]+prices[i]
            dp[i][3]=dp[i-1][2]
        return max(dp[-1][3],max(dp[-1][1],dp[-1][2]))

714 买卖股票时的最佳时机含手术费
给定一个整数数组 prices,其中 prices[i]表示第 i 天的股票价格 ;整数 fee 代表了交易股票的手续费用。

你可以无限次地完成交易,但是你每笔交易都需要付手续费。如果你已经购买了一个股票,在卖出它之前你就不能再继续购买股票了。

返回获得利润的最大值。

注意:这里的一笔交易指买入持有并卖出股票的整个过程,每笔交易你只需要为支付一次手续费。

class Solution:
    def maxProfit(self, prices: List[int], fee: int) -> int:
        dp=[[0]*2 for _ in range(len(prices))]
        dp[0][0]=-prices[0]
        dp[0][1]=0#-fee
        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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值