The focus of this week's lecture is still on dynamic programming, mainly on tree dp, state compression dp, Floyd-Warshall algorithm. This is a typical tree DP problem, the difficulty is Medium.
Original title:
The thief has found himself a new place for his thievery again. There is only one entrance to this area, called the "root." Besides the root, each house has one and only one parent house. After a tour, the smart thief realized that "all houses in this place forms a binary tree". It will automatically contact the police if two directly-linked houses were broken into on the same night.
Determine the maximum amount of money the thief can rob tonight without alerting the police.
Example 1:
3 / \ 2 3 \ \ 3 1
Maximum amount of money the thief can rob = 3 + 3 + 1 = 7.
Example 2:
3 / \ 4 5 / \ \ 1 3 1
Maximum amount of money the thief can rob = 4 + 5 = 9.
Thought: The main idea of the topic is that in a tree, at most one point can be stolen from two points connecting one side. If two points are stolen at the same time, the police will be alerted. Obviously, this is an almost bare tree dp, which can be done by recursive traversal of trees. The sub-problem of this problem is the maximum that a tree with a vertex as its root can steal. The maximum value that a parent node can steal is certainly related to the maximum value that its left and right subtrees can steal. This is dynamic programming. What does it matter? To find the maximum value of a tree where a parent node is located, there are two cases: one is that the parent node itself includes the left and right child nodes, and the other is that the parent node itself does not include the left and right child nodes, and then the left and right child nodes can be included or not. The maximum of these two cases is the result we require. Therefore, for a node, we only need to maintain two values of that node. The maximum theft value of a tree rooted on that node is saved with include and the maximum theft value of a tree rooted on that node is saved with not_include. A node include value = lefttree.not_include+righttree.not_include + the node val; a node not_include value = max(lefttree.not_include,lefttree.include)+max(righttree.not_include,righttree.include). In fact, the above is the state transition equation of the tree dp.
Code: 9ms through
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
//Save the maximum number of stolen trees rooted at a node
//Include denotes the maximum value when the node is included, and not_include denotes the maximum value when the node is not included.
struct result
{
int include,not_include;
};
class Solution {
result find(TreeNode* root){
result res;
//The case where the node is a leaf node
if(!root){
res.include=0;
res.not_include=0;
return res;
}else{
//The case of non-leaf nodes
result ltree,rtree;
ltree=find(root->left);
rtree=find(root->right);
res.include=ltree.not_include+rtree.not_include+root->val;
res.not_include=max(ltree.not_include,ltree.include)+max(rtree.not_include,rtree.include);
return res;
}
}
public:
int rob(TreeNode* root) {
result res;
res=find(root);
return max(res.include,res.not_include);
}
};
ps: We should also pay attention to the efficiency of recursive functions. The idea of the following code algorithm is exactly the same as the ac code mentioned above. Just because the recursive function is not written concisely enough, it is time-out! The code is as follows:
struct result
{
int include,not_include;
};
class Solution {
public:
result find(TreeNode* root){
result res;
if(!root){
res.include=0;
res.not_include=0;
return res;
}else{
//Each level of recursion contains four sub-functions, recursive scale index growth!
int left_not=find(root->left).not_include;
int left_in=find(root->left).include;
int right_not=find(root->right).not_include;
int right_in=find(root->right).include;
res.include=left_not+right_not+root->val;
res.not_include=max(left_not,left_in)+max(right_not,right_in);
return res;
}
}
int rob(TreeNode* root) {
result res;
res=find(root);
return max(res.include,res.not_include);
}
};