337. 打家劫舍 III
时间:2020年8月5日
知识点:二叉树、记忆化优化、递归
题目链接: https://leetcode-cn.com/problems/house-robber-iii/
题目
在上次打劫完一条街道之后和一圈房屋后,小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为“根”。 除了“根”之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果两个直接相连的房子在同一天晚上被打劫,房屋将自动报警。
计算在不触动警报的情况下,小偷一晚能够盗取的最高金额。
示例1
输入:
[3,2,3,null,3,null,1]
3
/ \
2 3
\ \
3 1
输出:
7
解释
小偷一晚能够盗取的最高金额 = 3 + 3 + 1 = 7.
示例2
输入:
[3,4,5,1,3,null,1]
3
/ \
4 5
/ \ \
1 3 1
输出:
9
解释
小偷一晚能够盗取的最高金额 = 4 + 5 = 9
解法
举例:
3
/ \
4 5
/ \
6 7
/ \
10 1
res = 4+7+10+1
- 记录每个节点上能获得最大的收益,递归解决
- 递归退出条件:1.空节点 2.这个节点计算过了
- 递归 这个收益 = max(这个节点能偷的+这个节点的孙子节点能偷的,这个节点的儿子节点能偷的)
- 记忆化搜索,避免每次递归,节省时间
代码
#include <stdio.h>
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
//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:
unordered_map<TreeNode* , int> f;
int rob(TreeNode* root) {
if(root == nullptr) return 0;
if(f.count(root)) return f[root]; //无需再次计算
int res = root->val;
if(root->left) //存在左节点,加上左边节点的儿子节点,也就是孙子节点的值
res += (rob(root->left->left) + rob(root->left->right));
if(root->right)
res += (rob(root->right->left) + rob(root->right->right));
//判断这个节点最大的值,res:这个点偷,rob(root->left)+rob(root->right):这个不偷
res =max(res,rob(root->left)+rob(root->right));
f[root] = res;
return res;
}
};
int main()
{
TreeNode root(3);
TreeNode node1(4);
TreeNode node2(5);
TreeNode node3(6);
TreeNode node4(7);
TreeNode node5(10);
TreeNode node6(1);
root.left = &node1;
root.right = &node2;
node1.left = &node3;
node2.right = &node4;
node3.left = &node5;
node3.right = &node6;
Solution s;
cout<<s.rob(&root);
}
今天也是爱zz的一天哦!