Leetcode 337. House Robber III
You are given the root of a binary tree representing houses along a street. Each node contains a non-negative integer representing the amount of money stashed in that house. The robber cannot rob two directly connected nodes (i.e., they cannot rob a parent and its direct child). Determine the maximum amount of money the robber can rob without alerting the police.
To solve this problem, we use a dynamic programming approach with depth-first search (DFS). The idea is to calculate two values for each node:
rob
: The maximum amount of money that can be robbed if we rob the current node.notRob
: The maximum amount of money that can be robbed if we don’t rob the current node.We traverse the tree bottom-up, starting from the leaf nodes, and propagate these values up to the root.
Here’s the C++ code to solve this problem:
#include <iostream>
#include <unordered_map>
// Definition for a binary tree node.
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode* left, TreeNode* right) : val(x), left(left), right(right) {}
};
class Solution {
public:
std::pair<int, int> robSub(TreeNode* root) {
if (!root) {
return {0, 0};
}
auto left = robSub(root->left);
auto right = robSub(root->right);
// If we rob this node, we cannot rob its children
int rob = root->val + left.second + right.second;
// Otherwise, we take the maximum of robbing or not robbing its children
int notRob = std::max(left.first, left.second) + std::max(right.first, right.second);
return {rob, notRob};
}
int rob(TreeNode* root) {
auto result = robSub(root);
return std::max(result.first, result.second);
}
};
int main() {
// Construct the tree
TreeNode* root = new TreeNode(3);
root->left = new TreeNode(2);
root->right = new TreeNode(3);
root->left->right = new TreeNode(3);
root->right->right = new TreeNode(1);
Solution solution;
std::cout << "Maximum amount of money that can be robbed: " << solution.rob(root) << std::endl;
return 0;
}
rob
(if we rob the current node)notRob
(if we do not rob the current node).robSub
on the root and returns the maximum of robbing or not robbing the root.The time complexity of this solution is (O(n)), where (n) is the number of nodes in the tree. This is because each node is visited once, and the computation done at each node (calculating the two values) is constant time.
The space complexity is (O(h)), where (h) is the height of the tree, due to the recursive call stack. In the case of a balanced tree, the height (h) is (O(\log n)), and in the case of a skewed tree, it is (O(n)).
Got blindsided by a question you didn’t expect?
Spend too much time studying?
Or simply don’t have the time to go over all 3000 questions?