【算法训练】动态规划 打家劫舍系列 python javascript

js代码主要是为了练手,所以算法逻辑和python是一模一样的

一、打家劫舍 198

在这里插入图片描述

1、分析

标准动态规划
每个房子只有两个状态,抢或者不抢。有一个约束条件,相邻房子不能同时抢。所以可以得到如下的动态转移方程

dp[i] = max(dp[i-1],dp[i-2]+nums[i])

为了编程方便,我们从尾向前计算,所以动态转移方程为

dp[i] = max(dp[i+1],dp[i+2]+nums[i])

具体见代码

2、代码

python

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

JS

/**
 * @param {number[]} nums
 * @return {number}
 */
var rob = function(nums) {
    let n = nums.length;
    let dp = Array(n+2).fill(0);
    for(let i=n-1;i>=0;i--){
        dp[i] = Math.max(dp[i+1],dp[i+2]+nums[i]);
    }
    return dp[0];

};

二、打家劫舍 II 213

在这里插入图片描述

1、分析

可以看出 和第一题的差别就在于第一间房子和最后一间房子不能同时选择,所以我这里搞了两个DP数组来分别记录,不看开头和不看结尾房子的情况。其他和第一题没有区别。最后找到两种情况下的最大值即可。

2、代码

python

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

        dp1 = [0]*(n+2)
        dp2 = [0]*(n+2)
        for i in range(n-1,0,-1):
            dp1[i] = max(dp1[i+1],dp1[i+2]+nums[i])
        for i in range(n-2,-1,-1):
            dp2[i] = max(dp2[i+1],dp2[i+2]+nums[i])
        return max(dp1[1],dp2[0])
/**
 * @param {number[]} nums
 * @return {number}
 */
var rob = function(nums) {
    let n = nums.length;
    if(n==1){
        return nums[0];
    }
    let dp1 = Array(n+2).fill(0);
    let dp2 = Array(n+2).fill(0);
    for(let i=n-1;i>=1;i--){
        dp1[i] = Math.max(dp1[i+1],dp1[i+2]+nums[i]);
    }
    for(let i=n-2;i>=0;i--){
        dp2[i] = Math.max(dp2[i+1],dp2[i+2]+nums[i]);
    }
    return Math.max(dp1[1],dp2[0])

};

三、打家劫舍 III 337

1、分析

以二叉树的形式,展示。如果偷了当前结点,那么就不可以偷其左右孩子结点了,若未偷当前结点,则可以其左右子节点可偷也可不偷,找到最大值即可。
用一个数组记录当前结点偷与不偷得到的最大值。res[0]表示偷,res[1]表示不偷。

详细看代码

2、代码

# 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: TreeNode) -> int:

        def helper(node):
            if not node:
                return [0,0]
            res = [0]*2 #用于记录当前结点偷与不偷的最大值
            left = helper(node.left)
            right = helper(node.right)
            res[0] = max(left[0],left[1])+max(right[0],right[1]) #若当前结点不偷,则其左右子节点可偷可不偷
            res[1] = node.val+left[0]+right[0] #若当前结点要偷,则其左右子节点都不可偷
            return res
        temp = helper(root)
        return max(temp)

JS

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number}
 */
var rob = function(root) {
    let res = helper(root);
    return Math.max(res[0],res[1]);
};

var helper = function(node){
    if(node===null){
        return [0,0];
    }
    let left = helper(node.left);
    let right = helper(node.right);
    let not_rob = Math.max(left[0],left[1])+Math.max(right[0],right[1]);
    let do_rob = node.val+left[0]+right[0];
    return [not_rob,do_rob];
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值