Leetcode337. 盗贼问题

来源:互联网 发布:javascript的发展现状 编辑:程序博客网 时间:2024/04/27 17:01

Leetcode337. House Robber III

题目

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 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.

解题分析

乍一看,这个问题表现出“最优子结构”的特点:如果我们想从当前的二叉树(根源)中抢夺最大的金额,我们当然希望我们可以对其左右子树做同样的事情。

因此,根据这个思路,我们来定义函数rob(root),它将返回我们可以抢夺以根为根的二叉树的最大金额;现在的关键是从解决其子问题,即如何从rob(root.left),rob(root.right)等等获取rob(root)。

显然上面的分析提出了一个递归的解决方案。而对于递归,总是有必要弄清楚以下两个属性:
终止条件:我们什么时候知道抢劫(根)的答案,而没有任何计算?当然,当树空了——我们没有什么可抢的,所以金额是零。
递归关系:即如何从rob(root.left),rob(root.right)等等获取rob(root)。从树根的角度来看,最后只有两个场景:根被抢劫或没有被抢劫。如果是这样,由于“我们不能抢夺任何两个直接关联的房子”的限制,下一层可用的子树就是四个“孙子树”(root.left.left,root.left.right ,root.right.left,root.right.right)。但是,如果root不被抢劫,则下一级可用子树就是两个“子树”(root.left,root.right)。我们只需要选择产生更多金钱的场景。

源代码

/** * 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) {        if (root == NULL) {            return 0;        }        int val = 0;        if (root->left != NULL) {            val += rob(root->left->left) + rob(root->left->right);        }        if (root->right != NULL) {            val += rob(root->right->left) + rob(root->right->right);        }        return max(val + root->val, rob(root->left) + rob(root->right));    }};

以上是我对这道问题的一些想法,有问题还请在评论区讨论留言~

原创粉丝点击