题目地址:
https://www.lintcode.com/problem/maximum-subtree/description
给定一棵二叉树,求其和最大的子树,返回其树根。
法1:分治。由于结果只有三种可能,要么在左子树中,要么在右子树中,要么就是root本身,所以可以用分治来做。但需要注意的是,由于要求一下当前树的节点和,就需要递归求解左右子树的节点和,如果不记录下来的话就会造成重复计算的问题。所以我们用一个哈希表记录每个子树的节点和是多少,做一下记忆化。代码如下:
import java.util.HashMap;
import java.util.Map;
public class Solution {
/**
* @param root: the root of binary tree
* @return: the maximum weight node
*/
public TreeNode findSubtree(TreeNode root) {
// write your code here
if (root == null) {
return root;
}
Map<TreeNode, Integer> map = new HashMap<>();
// 空树节点和记为0
map.put(null, 0);
return find(root, map);
}
private TreeNode find(TreeNode root, Map<TreeNode, Integer> map) {
if (root == null) {
return null;
}
TreeNode left = find(root.left, map), right = find(root.right, map);
// 分别计算本树以及左右子树的节点和,
// 由于是递归计算的,所以算完root节点和后左右子树的节点和都已经存在哈希表里了,可以直接拿出来
int sum = sum(root, map), lSum = map.get(left), rSum = map.get(right);
if (left == null && right == null) {
return root;
} else if (right == null) {
return sum >= lSum ? root : left;
} else if (left == null) {
return sum >= rSum ? root : right;
} else {
if (sum >= Math.max(lSum, rSum)) {
return root;
} else {
return lSum >= rSum ? left : right;
}
}
}
private int sum(TreeNode root, Map<TreeNode, Integer> map) {
// 如果已经有了记忆则调取记忆
if (map.containsKey(root)) {
return map.get(root);
}
// 否则递归求解并把结果放进哈希表
map.put(root, sum(root.left, map) + sum(root.right, map) + root.val);
// 最后返回
return map.get(root);
}
}
class TreeNode {
int val;
TreeNode left, right;
TreeNode(int x) {
val = x;
}
}
时空复杂度 。
法2:DFS。用全局变量记录已经找到的最大和和树根,然后边DFS边计算当前子树的和,边更新全局变量。代码如下:
public class Solution {
int maxSum = Integer.MIN_VALUE;
TreeNode res = null;
/**
* @param root: the root of binary tree
* @return: the maximum weight node
*/
public TreeNode findSubtree(TreeNode root) {
// write your code here
if (root == null) {
return root;
}
// 计算所有子树的和并更新全局变量
sum(root);
return res;
}
private int sum(TreeNode root) {
if (root == null) {
return 0;
}
// 分治
int left = sum(root.left), right = sum(root.right);
int total = left + right + root.val;
if (maxSum < total) {
maxSum = total;
res = root;
}
return total;
}
}
时间复杂度 ,空间 。