337. House Robber III

探讨在一棵二叉树型结构的社区中,如何在不触动报警条件下实现最大金额的抢劫。采用动态规划思想,递归解决子问题,通过比较左右子树的最优解来确定整体最优解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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.

题意:如之前的house robberI & II,假设房子的构造是二叉树型的,父子结点不能同时偷窃,则问最大的偷窃方案。

思路:

1. 动态规划的思想是通过(存储)局部的最优解,在局部最优解的基础上,通过进一步决策,达到全局的最优解。当然,局部面临的问题与全局面临的问题具有相似性。

2. 以该题为例,求解这棵树root的最优解,那么我假设左子树和右子树的最优解情况我已经知道,那么我想知道整颗树的最优解,就需要知道取root的val时,最优解是多少,还要知道不取root->val时的最优解多少,从而比较即可知道整颗树的最优解。取root->val时,最优解=不取左子树跟结点时,左子树的最优解+不取右子树的跟结点时右子树的最优解+root->val;不取root->val时,最优解=左子树的最优解+右子树的最优解。左子树的最优解=max{ 取左子树根结点时最优解, 不取左子树跟结点时最优解 }。

3. 同理局部子问题(以左子树为例),左子树也是一颗树,也存在左子树的根结点取和不取时最优的问题,假设左子树跟结点取和不取的最优值分别为left, nleft;右子树的对应值right,nright

4. 那么整棵树的取和不取时的最优值分别别表示为:with=nleft+nright+root->val, without=max(left, nleft)+max(right, nright)

5. 决策的时候即是比较大小即可。子问题同样如此递归处理。

/**
 * 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) {
		int with, without;
		dfs(root, with, without);
		return max(with, without);
	}

	void dfs(TreeNode* root, int& with, int& without){
		if (root == NULL){
			with = 0;
			without = 0;
			return;
		}

		int left, nleft;
		int right, nright;

		dfs(root->left, left, nleft);
		dfs(root->right, right, nright);

		with = nleft + nright + root->val;
		without = max(left, nleft) + max(right, nright);
	}	
};




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值