题目地址:
https://www.lintcode.com/problem/house-robber-iii/
给定一棵二叉树,要求选取一些节点使得任意两个节点不相邻并且节点总和最大。求那个最大值。
这是个树上DP问题。设树根为 x x x,若取 x x x则最大和为 f [ x ] f[x] f[x],若不取 x x x则最大和为 g [ x ] g[x] g[x],显然想要求的答案就是 max { f [ x ] , g [ x ] } \max\{f[x],g[x]\} max{f[x],g[x]}。而 f [ x ] = x . v + g [ x . l ] + g [ x . r ] g [ x ] = max { f [ x . l ] , g [ x . l ] } + max { f [ x . r ] , g [ x . r ] } f[x]=x.v+g[x.l]+g[x.r]\\g[x]=\max\{f[x.l],g[x.l]\}+\max\{f[x.r],g[x.r]\} f[x]=x.v+g[x.l]+g[x.r]g[x]=max{f[x.l],g[x.l]}+max{f[x.r],g[x.r]}只需要DFS一遍就可以得到。代码如下:
public class Solution {
/**
* @param root: The root of binary tree.
* @return: The maximum amount of money you can rob tonight
*/
public int houseRobber3(TreeNode root) {
// write your code here
int[] dp = dfs(root);
return Math.max(dp[0], dp[1]);
}
// 返回一个长度为2的数组,第一个数字是不取root所得最大和,第二个数字是取root所得最大和
private int[] dfs(TreeNode root) {
if (root == null) {
return new int[]{0, 0};
}
int[] left = dfs(root.left), right = dfs(root.right);
int[] dp = {0, 0};
dp[0] = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);
dp[1] = root.val + left[0] + right[0];
return dp;
}
}
class TreeNode {
int val;
TreeNode left, right;
public TreeNode(int val) {
this.val = val;
}
}
时间复杂度 O ( n ) O(n) O(n),空间 O ( h ) O(h) O(h)。