代码随想录算法训练营第四十八天 | 198.打家劫舍,213.打家劫舍II,337.打家劫舍III

目录

198.打家劫舍

213.打家劫舍II

337.打家劫舍III


198.打家劫舍

题目链接:198. 打家劫舍

(1)dp[ i ] 表示经过前 i 户所偷的最高金额,且偷第 i 户;

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

(3)dp[ 0 ] = nums[ 0 ]; dp[ 1 ] = nums[ 1 ]; dp[ 2 ] = nums[ 2 ] + nums[ 0 ];

(4)从小到大遍历房屋;

class Solution {
public:
    int rob(vector& nums) {
        if(nums.size() == 1)    return nums[0];
        int dp[110] = {0};
        dp[1] = nums[0];
        dp[2] = nums[1];
        for(int i = 3; i <= nums.size(); ++i){
            dp[i] = max(dp[i - 2], dp[i - 3]) + nums[i - 1];
        }
        return max(dp[nums.size()], dp[nums.size() - 1]);
    }
};

或者可以让 dp[ i ] 的含义仅为前 i 户所偷的最高金额,则

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

213.打家劫舍II

题目链接:213. 打家劫舍 II

第一反应是,可以将偷取方式分为两部分:从 1 到 n-1、从 2 到 n,然后进行比较。

class Solution {
public:
int rob1(vector& nums, int start, int end) {
        if(end - start == 1)    return nums[start];
        int dp[110] = {0};
        dp[start] = nums[start];
        dp[start + 1] = max(nums[start], nums[start + 1]);
        for(int i = start + 2; i < end; ++i){
            dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]);
        }
        return dp[end - 1];
    }

    int rob(vector& nums) {
        if(nums.size() == 1)    return nums[0];
        return max(rob1(nums, 0, nums.size() - 1), rob1(nums, 1, nums.size()));
    }
};

337.打家劫舍III

题目链接:337. 打家劫舍 III

本题应当使用后序遍历,将子树的情况汇总到父节点,判断父节点是否偷取。

dp0 表示本节点不偷取,dp1 表示本节点偷取;

对于每个父节点,有四种情况:

1. 左孩子偷取,右孩子不偷取;不偷取。

2. 左孩子不偷取,右孩子偷取;不偷取。

3. 左孩子偷取,右孩子偷取;不偷取。

4.左孩子不偷取,右孩子不偷取;偷取。

class Solution {
public:
    void traversal(TreeNode* cur, int& dp0, int& dp1){
        if(cur == NULL){
            dp0 = 0;    dp1 = 0;
        }
        int left_dp0, left_dp1, right_dp0, right_dp1;
        left_dp0 = left_dp1 = right_dp0 = right_dp1 = 0;
        if(cur->left)    traversal(cur->left, left_dp0, left_dp1);
        if(cur->right)    traversal(cur->right, right_dp0, right_dp1);
        dp0 = max(left_dp0, left_dp1) + max(right_dp0, right_dp1);
        dp1 = left_dp0 + right_dp0 + cur->val;
    }
    int rob(TreeNode* root) {
        int dp0, dp1 = 0;
        traversal(root, dp0, dp1);
        return max(dp0, dp1);
    }
};

你可能感兴趣的:(动态规划,算法,c++,leetcode)