337. House Robber III
一个小偷进入一个小区偷东西,小区是一个二叉树,只有一个入口,即root,不能偷任何相邻的两个房子,每个房子可以偷的金钱不一,要求偷的金额最大。
- 后序遍历每个结点,获取当前结点左子树的结果和右子树的结果,进行相加获得sum1
- 当前结点如果存在左右子结点,就获取它左孩子的左右子树的结果之和,右孩子的左右子树的结果之和,将他们相加再与该结点值相加获得sum2
- 比较sum1和sum2,将较大值作为以当前结点为根结点的结果进行返回
- 但是这样会很慢,因为有很多的重复计算
- 通过一个hashmap记录每个结点的结果进行优化,每遍历到一个结点时看看hashmap是是否有当前结点的结果,有就直接使用,没有就执行上面的步骤,并将结果添加到hashmap中
public int rob(TreeNode root) {
if (root == null) return 0;
HashMap<TreeNode, Integer> map = new HashMap<>();
return helper(root, map);
}
public int helper(TreeNode root, HashMap<TreeNode, Integer> map) {
if (root == null) return 0;
if (map.containsKey(root)) return map.get(root);
int sum = 0;
if (root.left != null) {
sum += helper(root.left.left, map) + helper(root.left.right, map);
}
if (root.right != null) {
sum += helper(root.right.left, map) + helper(root.right.right, map);
}
int res = Math.max(sum + root.val, helper(root.left, map) + helper(root.right, map));
map.put(root, res);
return res;
}
979. Distribute Coins in Binary Tree
给一个二叉树,共有n个结点,每个结点都有大于等于0个硬币,总共有n个硬币,将硬币从一个结点移动到另一个结点上算一步,求最小需要多少步可以将硬币移动到所有结点上(即每个结点上都有且只有一个硬币。)
将二叉树看作有一个根结点和一个左子树和一个右子树这样三个部分,那么总共移动的步数就是:根结点硬币数-1 + 左子树移动的步数 + 右子树移动的步数 的绝对值:
int res = 0;
public int distributeCoins(TreeNode root) {
helper(root);
return res;
}
public int helper(TreeNode root) {
if (root == null) return 0;
int val = root.val-1 + helper(root.left) + helper(root.right);
res += Math.abs(val);
return val;
}