Leetcode刷题笔记 337. 打家劫舍 III

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. 递归退出条件:1.空节点 2.这个节点计算过了
  3. 递归 这个收益 = max(这个节点能偷的+这个节点的孙子节点能偷的,这个节点的儿子节点能偷的)
  4. 记忆化搜索,避免每次递归,节省时间

代码

#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的一天哦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值