Leetcode题解:198.213.337.House Robber套题

198.213.337.House Robber套题

难度:Easy-Medium-Hard

题目

You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night.

Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police.

中文简述

House Robber讲的就是一个小偷去盗窃一个别墅区,住户的安保系统是关联在一起的,只要有相邻的两个住户都被偷就会激活报警系统。已知每个住户中可以盗窃的金额,问小偷如何在不触发报警系统的前提下盗取最高金额。
House Rober I:住户为直线型排列,难度Easy
House Rober II:住户为环形排列,难度Medium
House Rober III:住户为二叉树形,父节点与子节点相邻,难度Hard

解题思路

通过读题,很容易看出这是一道典型的动态规划问题,难度也随着拓扑模型复杂度增加而变难,但状态转移方程始终保持不变:
d[n]=max{d[n-1], d[n-2]+m[n]}
其中d[n]为到第n+1座房子所能偷到的最高金额,m[n]为每座房子所能偷的金额。思想也很朴素:到第n+1所房子的方案为n-2前最高金额方案加上该房子金额 和 n-1前最高金额方案高的一方。
对于直线型结构,很明显我们只要从开始一直扫到结尾,就可以获得d[n]的最高金额(需要方案也可以保存对于n偷还是不偷:偷,则方案为包括该节点间隔取点的方案;不偷,则为从n-1往前间隔 )。
对于环形结构,则首尾也是相邻的,所以我们要打出2张表,一张取首一张取尾,然后对比两者哪一个最大。(代码里面取尾方案则是从尾部往前扫获得,最终比较dp1[n-1]和dp2[0])
对于二叉树型结构,采取后序遍历的形式,将包括子节点的方案和不包括子节点方案+该节点值的总和进行比较取较大者。
思路说清楚,代码也就很好实现了。

//House RobberI
class Solution {
public:
    int rob(vector<int>& nums) {
        if(nums.empty())
            return 0;
        vector<int> ans;
        ans.push_back(nums[0]);
        ans.push_back(max(nums[0], nums[1]));
        for(int i = 2; i < nums.size(); i++){
            ans.push_back(max(nums[i]+ans[i-2], ans[i-1]));
        }
        return ans[nums.size()-1];
    }
};
House RobberII:
class Solution {
public:
    int rob(vector<int>& nums) {
        if(nums.empty())
            return 0;
        int len = nums.size();   
        if(len == 1)
            return nums[0];
        vector<int> dp1(len), dp2(len);
        dp1[0]=nums[0]; dp1[1]=max(nums[0],nums[1]);
        dp2[len-1]=nums[len-1] ; dp2[len-2] = max(nums[len-1],nums[len-2]);
        for(int i=2; i < len-1; i++){
            dp1[i] = max(dp1[i-2]+nums[i], dp1[i-1]);
        }
        for(int i=len-3; i > 0; i--){
        //scan from the end & dp2[0]is maxvalue including nums[n-1]
            dp2[i] = max(dp2[i+2]+nums[i], dp2[i+1]);
        }
        return max(dp1[len-2], dp2[1]);

    }
};
House RobberIII:
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:

    int rob(TreeNode* root) {
        vector<int> ans = findMax(root);
        return max(ans[0], ans[1]);
    }

    //post-Oder
    vector<int> findMax(TreeNode* root){
        vector<int> ans(2,0);   //ans[0] show don't cur_val, ans[1] show take cur_val;
        if(root == NULL)
            return ans;
        vector<int> lans = findMax(root->left);
        vector<int> rans = findMax(root->right);
        ans[0]=max(lans[0],lans[1]) + max(rans[0],rans[1]);
        ans[1]=root->val + lans[0] + rans[0];
        return ans;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值