刷题python,力扣198,213,337三个打家劫舍问题。动态规划

首先先给出题目的地址。https://leetcode-cn.com/problems/house-robber-iii/(https://leetcode-cn.com/problems/house-robber-iii/)
在这里插入图片描述
首先是简单版的打家劫舍,这是题是一维dp,考虑状态方程,dp[i]是到i为止,获取最大的收益,那么dp[i]就等于他这次没偷,第i-1次的最大收益和这次偷了的收益加上第i-2次的最大收益,
dp[i]=max(dp[i-1],dp[i-2]+nums[i]),显然dp[0]=nums[0],dp[1]=max(nums[0],nums[1]).python代码如下:

class Solution:
    def rob(self, nums: List[int]) -> int:
        if not nums:
            return 0
        if len(nums)==1:
            return nums[0]###前面是特殊的情况处理
        dpc = [0]* len(nums)
        dpc[0] = nums[0]
        dpc[1] = max(nums[1],nums[0])###赋初值
        for i in range(2,len(nums)):
            dpc[i] = max(dpc[i-2]+nums[i],dpc[i-1])###状态转移方程
        return dpc[-1]

在这里插入图片描述
升级版打家劫舍,和上题一样,就是多了个首尾也算相邻的。可以考虑去头去尾,分别做一次打家劫舍,然后去最大值就OK了。

class Solution:
    def rob(self, nums: List[int]) -> int:
        if not nums :
            return 0
        if len(nums)==1:
            return nums[0]
        if len(nums)==2:
            return max(nums)
        def get(nums):
            dpc = [0]*(len(nums))
            dpc[0] ,dpc[1] = nums[0],max(nums[0],nums[1])      
            for i in range(2,len(nums)):
                dpc[i] = max(dpc[i-2]+nums[i],dpc[i-1])
            return dpc
            
        return max(get(nums[1:])[-1],get(nums[:-1])[-1])####返回两次的最大值

终极版打家劫舍问题。
在这里插入图片描述
这是一道树形dp的题目,意思还是和之前一样相邻位置不能同时偷盗。
我们可以这样考虑,考虑某个节点可以取得的最大值,可以将其分为当前节点p,孩子节点h,和孩子节点的孩子节点s,那么对于p节点来说他的最大值有哪些可能呢?
1,当前节点p选择,那么p点的最大值就是当前节点和其左右孩子节点的孩子节点(也就是所有孙子节点)的最大值。
2,当前节点p不选择,那么他的最大值就有些复杂了。
2-1,首先左右孩子节点的都选择的最大之和。
2-2,其次是左右孩子都不选的最大之和
2-3 然后就是左孩子选择右孩子不选之和
2-3 最后就是左孩子不选右孩子选择之和这四种情况。
代码还是比较简单的。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def __init__(self):
        self.ans = 0
    def rob(self, root: TreeNode) -> int:        
        def rob2(root):
            if not root:
                return (0,0)
            nl,l = rob2(root.left)
            nr,r = rob2(root.right)
            my = root.val 
            nchoose = max(l+r,nl+nr,l+nr,nl+r)####当前节点不选的最大值就是四种情况的最大值
            choose = nl+nr+my     ####当前节点选择的最大值就是左右孩子都选的最大值      
            self.ans = max(self.ans,nchoose,choose)         
            return (nchoose,choose) ####每次返回两个值,一个是当前节点选择取得的最大的值,一个是当前节点不选取得的最大值
        rob2(root)
        return self.ans

这道题目理解之后感觉还是不算特别难的。

猜你喜欢

转载自blog.csdn.net/qq_42232193/article/details/105727857