打家劫舍1-4

leetcode198 打家劫舍

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。

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

 

示例 1:

输入:[1,2,3,1]
输出:4
解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
     偷窃到的最高金额 = 1 + 3 = 4 。
示例 2:

输入:[2,7,9,3,1]
输出:12
解释:偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。
     偷窃到的最高金额 = 2 + 9 + 1 = 12 。
 

提示:

1 <= nums.length <= 100
0 <= nums[i] <= 400

# 状态转移方程为dp[i] = max(dp[i-1], dp[i-2] + nums[i])
# dp[0] = 第一个 dp[1] = max(dp[0],nums[1])

class Solution:
    def rob(self, nums: List[int]) -> int:
        if (len(nums)==1):
            return nums[0]

        dp = [0 for i in range(len(nums))]

        dp[0] = nums[0]
        dp[1] = max(nums[1],dp[0])

        for i in range(2, len(nums)):
            dp[i] = max(dp[i-2]+nums[i], dp[i-1])
        
        return dp[len(nums)-1]

leetcode198 打家劫舍2  与  I 类似,但房屋是环形排列的,即第一间房屋和最后一间房屋相邻。

由于房屋是环形排列的,不能同时偷窃第一间和最后一间房屋。因此,可以将问题分解为两个子问题:偷窃第一间房屋但不偷窃最后一间房屋,以及不偷窃第一间房屋但可能偷窃最后一间房屋。然后分别计算这两个子问题的最大金额,并取两者中的较大值。

class Solution:
    def rob(self, nums: List[int]) -> int:

        if not nums :
            return 0
        if len(nums)==1:
            return nums[0]
        # 调用两次打家劫舍1
        ret1 = self.rob_s(nums[0:-1])
        ret2 = self.rob_s(nums[1:])
        # print(ret1,ret2)
        return max(ret1,ret2)

    def rob_s(self, nums:List[int]): 
        
        if not nums:
            return 0
        dp = [0 for i in range(len(nums))]
        dp[0] = nums[0]
        if len(nums) > 1:
            dp[1] = max(dp[0], nums[1])
        for i in range(2, len(nums)):
            dp[i] = max(dp[i-1],dp[i-2]+nums[i])
        
        return dp[-1]

leetcode 337 打家劫舍3 小偷意识到所有住户是个二叉树结构了, md, 这小偷一定是个失业狗程序,可能就是以后的劳资啊

思路: 递归调用抢当前节点 则不抢左右子节点,  不抢当前节点, 则可以选择抢或不抢左右子节点

/**
 * Definition for a binary tree node.
 * class TreeNode {
 *     public $val = null;
 *     public $left = null;
 *     public $right = null;
 *     function __construct($val = 0, $left = null, $right = null) {
 *         $this->val = $val;
 *         $this->left = $left;
 *         $this->right = $right;
 *     }
 * }
 */
class Solution {

    /**
     * @param TreeNode $root
     * @return Integer
     */
    function rob($root) {
        # 需要递归调用
        # 返回抢劫当前节点或者不抢劫当前节点
        $ret = $this->rob_s($root);
        return max($ret);
    }

    function rob_s($node){
        # null 强不强都一样是0
        if ($node == null) return [0,0];
        
        # 抢或不抢 左右子节点的返回 
        $left = $this->rob_s($node->left);
        $right = $this->rob_s($node->right);

        # 抢当前, 则不能抢左右子节点
        $rob_curr = $node->val + $left[1] + $right[1];

        # 不强当前, 则可以选择 抢或不抢 左右子节点
        $rob_notcurr = max($left[0],$left[1]) + max($right);
        
        return [$rob_curr,$rob_notcurr];
    }


}

leetcode 2560 打家劫舍4  让小偷最多窃取k个住户, k个住户中的最多的钱就是他的最小窃取能力,返回其k时的最小窃取能力

// 搞一把回溯玩玩,  时间不多了, 以后弄吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值