一个很有意思的问题,一个社区,所有的房子构成一棵二叉树,每个房子里有一定价值的财物,这棵二叉树有一个根节点root。如果相邻的两座房子同时被进入,就会触发警报。一个小偷,最初只能访问root节点,并可以通过二叉树的边访问房子(注:访问不意味着进入),请问不触发警报的前提下他能偷到的财物的最大价值是多少?
以下面这棵二叉树为例,最多能偷走3+3+1=7的财物
3
/ \
2 3
\ \
3 1
分析:
这个问题乍一看上去可能没什么思路,但是如果是用递归,可以很优雅的解决这个问题,这需要读者对递归有比较深刻的理解。下面给出解决这个问题的java代码:
package houseRobberIII;
import java.util.HashMap;
import java.util.Map;
import common.TreeNode;
public class Solution {
//使用一个cache 缓存以每个节点为根节点的rob方法返回值,减少计算量
Map<TreeNode, Integer> cache = new HashMap<TreeNode, Integer>();
public int rob(TreeNode root) {
//如果当前节点为空 直接返回0
if(null == root){
return 0;
}
//首先查看缓存中有没有这个节点的rob方法返回值
if(null != cache.get(root)){
return cache.get(root);
}
//计算当前节点左孩子的rob方法返回值
int maxLeft = rob(root.left);
//计算当前节点右孩子的rob方法返回值
int maxRight = rob(root.right);
int maxLeftLeft = 0;
int maxLeftRight = 0;
//如果当前节点有左孩子
if(null != root.left){
//计算其左孩子的左孩子的rob值
maxLeftLeft = rob(root.left.left);
//计算其左孩子的右孩子的rob值
maxLeftRight = rob(root.left.right);
}
int maxRightLeft = 0;
int maxRightRight = 0;
//如果当前节点有右孩子
if(null != root.right){
//计算其右孩子的左孩子的rob值
maxRightLeft = rob(root.right.left);
//计算其右孩子的右孩子的rob值
maxRightRight = rob(root.right.right);
}
//不偷当前节点能偷到的财物的最大值
int notIncludeCurrentNodeMax = maxLeft + maxRight;
//偷当前节点能偷到的财物的最大值
int includeCurrentNodeMax = maxLeftLeft + maxLeftRight + maxRightLeft + maxRightRight + root.val;
//以其中的较大值作为当前节点的rob方法返回值
int res = notIncludeCurrentNodeMax > includeCurrentNodeMax ? notIncludeCurrentNodeMax : includeCurrentNodeMax;
//缓存当前节点的rob方法返回值
cache.put(root, res);
return res;
}
}
package common;
/**
* 二叉树节点类
* @author xuguanglv
*
*/
public class TreeNode {
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode(int x) { val = x; }
}
这个解法中比较重要的一点是使用了cache进行动态规划,使整个算法的时间复杂度为O(V+E),其中V为二叉树的节点的数量,E为二叉树的边的数量;如果不使用cache来缓存每一个节点的rob方法返回值,每次访问某个节点,都要重复计算一次rob值,最后的时间复杂度将会是指数级的,显然不可接受的。
分享到:
相关推荐
含word文档,运行结果,c++源代码。项目功能包括输入一个二维数组A,自定义...求从A[0][0]开始的互不相邻的各元素之和;当数组的行数和列数相等(m=n)时,分别求两条对角线上的数据元素之和,否则打印出m!=n的信息。
C语言程序设计-编写程序。...⑴求出这8个数据的和、最大值、最小值及平均值。 ⑵求这8个数据的正数之和、负数之和(或正数与负数的个数); ⑶求这8个数据的奇数之和、偶数之和(或奇数与偶数的个数)。
在C语言中,处理数组和查找数组中的最大值与最小值是常见的编程任务。这个程序展示了如何实现这一功能。下面将详细解释程序的结构、工作原理以及如何优化它。 首先,程序定义了一个长度为3的整数数组`a[]`,但实际...
, xn,求这n 个数在实轴上相邻2 个数之间的最大差值。假设对任何实数的下取整函数耗时O(1),设计解最大间隙问题的线性时间算法。 编程任务:对于给定的n 个实数x1, x2,...,xn,编程计算它们的最大间隙。 Input ...
设n是一个正整数。现在要求将n分解为若干互不相同的自然数的和,且使这些自然数的乘积最大。
标题中的“随机抽取几个互不相等的值”是指在编程中实现一个功能,能够从一个特定的范围内(比如0到100)抽取一定数量的随机数,这些随机数之间不能重复。这个过程通常用于模拟、测试或者游戏等各种需要无重复随机数...
本文研究的是图论中关于图着色的问题,具体关注最大度顶点互不相邻的高度图的全色数。这里提到的高度图指的是图的一种特殊类型,而全色数是指在满足特定条件下给图的边和顶点赋予颜色的方法中所需要的最少颜色数。 ...
空间关系中两相邻实体最近距离算法的研究是一项涉及到计算机图形学、计算机视觉和地理信息系统(GIS)等多个领域的任务。在二维空间中,计算两个实体之间最近距离问题是一个常见的几何计算问题,通常用于地图分析、...
标题中的“自己实现的动态图片组件(多个组件时互不干扰)”表明这是一个关于自定义的、支持多实例并存且各实例之间不会相互影响的动态图片显示组件的讨论。动态图片通常指的是GIF格式的图像,它能连续播放一系列帧,...
数组a中已存有互不相同的10个整数从键盘输入一个整数,找出与该值相同的数组元素下标。 (如果没找到,输出“没找到”).c
5. 互不影响的滑动:为了实现不同类别滑动互不影响,每个类别应该被封装在一个独立的`swiper`组件内。通过设置独立的`current`属性,我们可以控制每个类别滑动的位置。同时,每个`swiper`的滑动事件不会影响其他类别...
有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?
二叉树的层次遍历及宽度,哈夫曼树,将L中的整数序列循环左移p个位置,将表L中所有值为x 的元素删除,判断链表中是否存在环,删除单链表L(L中元素值各不相同)的最大值所对应的结点,并返回该值,树的孩子兄弟表示...
通过社区划分技术可以区分社区内的连边和社区间的连边,从而实现更有针对性的处理。 #### 五、基于社区划分与连边逆序放回的网络分解算法(CD-IRE) 为了克服现有方法的局限性,本研究提出了一种新的网络分解算法...
2. **排序和去重法**:对于大量的随机数,可以先生成一个包含所有可能值的数组,然后进行随机排序,从而得到互不相同的随机数。这种方法更高效,但需要更多的内存。以下是使用该方法的示例: ```vba Sub ...
在编程领域,生成10个互不相同的字母并进行排序是一项常见的任务,特别是在算法练习、数据结构学习或者随机测试用例的创建中。这个任务主要涉及到两个关键知识点:随机数生成和排序。以下是对这两个核心概念的详细...
最优分解问题是一个经典的数学优化问题,它涉及到如何有效地将一个正整数n分解为若干个互不相同的自然数之和,以使得这些自然数的乘积最大化。这个问题在计算机科学和算法设计中有着广泛的应用,特别是在寻找高效...
本文将详细讲解如何实现XP系统的多用户远程登录,并确保各个用户间操作互不影响,做到“完美、简单、易操作”。 首先,Windows XP默认并不支持多个用户同时进行远程桌面连接,但通过一定的设置和第三方工具,可以...
- **互不相邻元素之和**:从左上角的元素`A[0][0]`开始,找到所有与其相邻的元素不相邻的元素,并计算它们的和。 - **对角线元素之和**:当m等于n时,计算两条对角线(主对角线和副对角线)上的元素之和。 #### 1.3...
经典填字游戏:在3*3个方格的方阵中要填入数字1到N(N>=10)内的某9个数字,每个方格填一个整数,使得所有相邻两个方格内的两个整数之和为质数。试求出所有满足这个要求的各种数字填法。 //我们可以通过改变N的值来...