LeetCode #337 - House Robber III - Medium

Problem

The thief has found himself a new place for his thievery again. There is only one entrance to this area, called the "root." Besides the root, each house has one and only one parent house. After a tour, the smart thief realized that "all houses in this place forms a binary tree". It will automatically contact the police if two directly-linked houses were broken into on the same night.

Determine the maximum amount of money the thief can rob tonight without alerting the police.

Example

Examlpe 1

     3
    / \
   2   3
    \   \ 
     3   1
Maximum amount of money the thief can rob = 3 + 3 + 1 = 7.

Example 2

     3
    / \
   4   5
  / \   \ 
 1   3   1
Maximum amount of money the thief can rob = 4 + 5 = 9.

Algorithm

整理一下题意:某小偷要在二叉树里面偷东西。二叉树每个节点表示一户人家,每个节点的值代表小偷能偷走的价值。小偷从根节点出发偷东西,要求不能连续偷相邻两个节点的值。问小偷能偷走的最大价值和是多少?

小偷问题的进化版,由一维数组到二维数组到现在的二叉树。由于之前做了一题是动态规划解题版本的,所以自然先想到这个思路。写成递归版本代码如下。

//类动规版本,Time Limit Exceeded
class Solution {
public:
    int rob(TreeNode* root) {
        if (root==NULL) return 0;
        int val = 0;
        if (root->left) {
            val += rob(root->left->left) + rob(root->left->right);
        }
        if (root->right) {
            val += rob(root->right->left) + rob(root->right->right);
        }
        return max(val + root->val, rob(root->left) + rob(root->right));
    }
};

完成题目后提交,未通过,显示Time Limit Exceeded,超时。果然直接递归会超时…

于是考虑新的方法。每个节点考虑选或不选两个状态。若选择了该节点,则子节点只能取不可选状态的结果。若未选择该节点,则子节点可选可不选,取二者较大的结果。

基于这个思路,可以设一个int向量result,result[0]表示当前节点选中的最大值,result[1]表示当前节点不选的最大值。在DFS函数中,由同样思路,用int向量res表示两种状态的结果,则有

不选节点:res[0]=max(l[0],l[1])+max(r[0],r[1]);
选节点:res[1]=l[0]+r[0]+p->val;

代码如下。

//DFS
class Solution {
public:
    int rob(TreeNode* root) {
        vector<int> result=dfs(root);
        return max(result[0],result[1]);
    }

    vector<int> dfs(TreeNode*p){
        if(p==NULL) return vector<int>(2,0);
        vector<int> l=dfs(p->left);
        vector<int> r=dfs(p->right);
        vector<int> res(2,0);
        res[0]=max(l[0],l[1])+max(r[0],r[1]);
        res[1]=l[0]+r[0]+p->val;
        return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值