LeetCode/打家劫舍(动态规划树)
小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为 root 。
除了 root 之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果两个直接相连的房子在同一天晚上被打劫 ,房屋将自动报警。
1. 特解记忆化搜索
从上往下递归的过程中,会有很多重复递归,将对应节点值存储起来,减少递归运算
这里使用哈希表对离散结构进行记忆化存储,这由于只需要记录一个状态的值,属于特解
class Solution {
public:
unordered_map<TreeNode*,int> m; //记录对应节点子树最大值,这里越过相邻节点进行判断,可以保证无后效性,所以只需记录一个值
int rob(TreeNode* root) {
if(!root) return 0;
if(m.count(root)) return m[root];
int val1 = root->val;
int val2 = 0;
val2+=rob(root->left);
val2+=rob(root->right);
if(root->left){
val1+=rob(root->left->right);
val1+=rob(root->left->left);
}
if(root->right){
val1+=rob(root->right->right);
val1+=rob(root->right->left);
}
m[root]= max(val1,val2);
return m[root];
}
};
2. 模板记忆化搜索
其实每个节点有偷与不偷两个状态,只需记录这两个状态,记忆化搜索即可,同时给出这两个状态转移的方法
class Solution {
public:
int rob(TreeNode* root) {
unordered_map <TreeNode*, int> memo[2];//对应节点偷与不偷的子树最大值
function<int(TreeNode* node, bool)> dfs = [&](TreeNode* node, bool state) -> int {
if(!node) return 0;
if(memo[state].count(node)) return memo[state][node];
if(!state) memo[state][node] = node->val + dfs(node->left,1)+dfs(node->right,1);
if(state) memo[state][node] = max(dfs(node->left,0),dfs(node->left,1)) + max(dfs(node->right,0),dfs(node->right,1));
return memo[state][node];
};
return max(dfs(root,0),dfs(root,1));
}
};
3. 树状动态规划
同时返回两种选择状态下的值,不需要记忆化存储,便于一次遍历的情况下完成状态的转移
class Solution {
public:
int rob(TreeNode* root) {
vector<int> res(2);
res = dfs(root);
return max(res[0],res[1]);
}
vector<int> dfs(TreeNode* root){//返回偷与不偷时的最大收益
vector<int> res(2);
if(!root) return res;
vector<int> left(2);
vector<int> right(2);
left = dfs(root->left);
right = dfs(root->right);
res[0] = left[1]+right[1]+root->val;
res[1] = max(left[0],left[1])+ max(right[0],right[1]);
return res;
}
};
4. 模板树状动态规划
struct SubtreeStatus {
int selected;
int notSelected;
};
class Solution {
public:
SubtreeStatus dfs(TreeNode* node) {
if (!node) return {0, 0};
auto l = dfs(node->left);
auto r = dfs(node->right);
int selected = node->val + l.notSelected + r.notSelected;
int notSelected = max(l.selected, l.notSelected) + max(r.selected, r.notSelected);
return {selected, notSelected};
}
int rob(TreeNode* root) {
auto rootStatus = dfs(root);
return max(rootStatus.selected, rootStatus.notSelected);
}
};

浙公网安备 33010602011771号