# Definition for a binary tree node.
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution:
def rob(self, root: TreeNode) -> int:
def helper(node):
if not node:
return (0, 0)
left = helper(node.left)
right = helper(node.right)
rob_this = node.val + left[1] + right[1]
not_rob_this = max(left) + max(right)
return (rob_this, not_rob_this)
return max(helper(root))
// Definition for a binary tree node.
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
class Solution {
public:
pair helper(TreeNode* node) {
if (!node) return {0, 0};
auto left = helper(node->left);
auto right = helper(node->right);
int rob_this = node->val + left.second + right.second;
int not_rob_this = max(left.first, left.second) + max(right.first, right.second);
return {rob_this, not_rob_this};
}
int rob(TreeNode* root) {
auto res = helper(root);
return max(res.first, res.second);
}
};
// Definition for a binary tree node.
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
class Solution {
public int rob(TreeNode root) {
int[] res = helper(root);
return Math.max(res[0], res[1]);
}
private int[] helper(TreeNode node) {
if (node == null) return new int[]{0, 0};
int[] left = helper(node.left);
int[] right = helper(node.right);
int rob_this = node.val + left[1] + right[1];
int not_rob_this = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);
return new int[]{rob_this, not_rob_this};
}
}
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
var rob = function(root) {
function helper(node) {
if (!node) return [0, 0];
const left = helper(node.left);
const right = helper(node.right);
const rob_this = node.val + left[1] + right[1];
const not_rob_this = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);
return [rob_this, not_rob_this];
}
const res = helper(root);
return Math.max(res[0], res[1]);
};
You are given the root node of a binary tree, where each node contains a non-negative integer value representing the amount of money stored in that house. The constraint is that if you rob a house (i.e., a node), you cannot rob its immediate children (left or right child nodes), because the police will be alerted.
Your task is to determine the maximum amount of money you can rob from the binary tree of houses without ever robbing two directly-linked houses. You must return a single integer representing this maximum sum.
At first glance, this problem seems similar to the classic House Robber problem, but with a twist: instead of a linear array of houses, the houses are organized in a binary tree. In the linear case, you can use dynamic programming by considering whether to rob or skip each house based on previous choices.
For the tree version, you must account for the fact that robbing a node prevents you from robbing its immediate children, but not its grandchildren. A brute-force approach would be to try all possible combinations of robbing or skipping each node, but this quickly becomes inefficient as the tree grows.
The key insight is to use recursion and, at each node, to keep track of two scenarios:
This approach ensures that at each node, you make the optimal decision based on the results of its subtrees, and you never recompute the same subproblem.
Consider the following binary tree:
3 / \ 2 3 \ \ 3 1
Let's trace the solution step by step:
So, the maximum amount of money that can be robbed is 7.
The House Robber III problem extends the classic dynamic programming paradigm to binary trees. By breaking the problem down into two scenarios at each node (rob or not rob), and propagating optimal results up from the leaves, we avoid redundant computations and achieve an efficient O(n) solution. The elegance of this approach lies in its simplicity and its adaptation of dynamic programming to tree structures, making it both efficient and easy to understand.