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

166 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路

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];
}