题目:
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.
思路:今日学了BFS,所以想用BFS做一下。具体做法为从上至下将各层的数字之和计入一个数组sum中。根据题目要求,不能去取相邻的两个元素,因此在此题中不能取相邻层的元素,即在sum数组中不能取相邻元素。此时的做法就与Leetcode 198. House Robber 的做法一样了:sum中元素个数为0时返回0,sum中元素个数为1时返回元素的数值,否则,定义一个数组,该数组中第i个元素表示在sum中取到第i个位置时,能偷的最大钱数max。max从另个值中取最大,其中一个是已经计算出的i-1位置上的值,另一个是i-2位置上的值加上sum[i]。这样,此数组的最后一个元素就是能偷到的最大钱数。
此思路的代码实现如下(C++实现):
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
#include<vector>
#define INT_MIN 0x80000000
class Solution {
public:
int rob(TreeNode* root) {
vector<TreeNode*> queue;
vector<int> level;
vector<int> sum;
int sum1 = 0;
int sum2 = 0;
if (root == NULL) return 0;
queue.insert(queue.begin(), root);
int target = 0;
int tmp = 0;
level.insert(level.begin(), 0);
while (!queue.empty()){
TreeNode* r = queue.back();
queue.pop_back();
int l = level.back();
level.pop_back();
if (target < l) {
sum.push_back(tmp);
tmp = r->val;
target ++;
}
else {
tmp += r->val;
}
if (r->left != NULL) {
queue.insert(queue.begin(), r->left);
level.insert(level.begin(), l + 1);
}
if (r->right != NULL) {
queue.insert(queue.begin(), r->right);
level.insert(level.begin(), l + 1);
}
}
sum.push_back(tmp);
int n = sum.size();
if (n == 0) return 0;
if (n == 1) return sum[0];
vector<int> res(n);
res[0] = sum[0];
for (int i = 1; i < n; i ++) {
res[i] = max(res[i - 1], (i == 1 ? 0 : res[i-2]) + sum[i]);
}
return res[n-1];
}
};
万万没想到!竟然不通过!因为从一开始思路就错了!因为这是二叉树!即使是相邻层中的元素,也可以加起来,因为它们也可能是不相邻的。比如下图中的情况!
最大值应该为4+3=7!
因此我们要换一种思路!
下面采用DFS来做。如果树不存在,则返回0;如果树只有一个根节点,则返回根节点的值;否则向下递归并定义son和grandson,其中son为左子树偷到的最大值和右子树偷到的最大值。grandson为此根节点的四个孙子分别偷到的最大值的和。将son和root->val+grandson进行比较并返回大的那个值。这样从下往上逐次累加最终就能得到结果!
具体代码实现如下;
代码:
C++实现
/**
* 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;
if (root->left == NULL && root->right == NULL) return root->val;
int son = 0;
int grandson = 0;
if (root->left != NULL) {
son += rob(root->left);
grandson += ((root->left->left != NULL ? rob(root->left->left) : 0) + (root->left->right != NULL ? rob(root->left->right) : 0));
}
if (root->right != NULL) {
son += rob(root->right);
grandson += ((root->right->left != NULL ? rob(root->right->left) : 0) + (root->right->right != NULL ? rob(root->right->right) : 0));
}
return max(son, root->val + grandson);
}
};