###### tags: `Leetcode` `medium` `dynamic programming` `tree` `dfs` `python` `c++` # 337. House Robber III ## [題目連結:] https://leetcode.com/problems/house-robber-iii/description/ ## 題目: The thief has found himself a new place for his thievery again. There is only one entrance to this area, called ```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 form a binary tree. It will automatically contact the police if **two directly-linked houses were broken into on the same night**. Given the ```root``` of the binary tree, return the maximum amount of money the thief can rob **without alerting the police**. ![](https://i.imgur.com/WtlR7fB.png) ![](https://i.imgur.com/kkyAi50.png) ## 解題想法: * Robber同類型題目: * [198. House Robber](/YIzmiuAqRfm6voICu36IXg) * [213. House Robber II](/STu5wzC9S0ePgRjfJwJCNQ) * 此題小偷新花樣: * 從tree中取值使和最大 * 規則是不能同時取相鄰的兩node * 遞迴解: time: O(n) * 分別用字典存,對於拜訪到n節點root時: * 字典1: **Ro[n]** * 搶該root,可得到最大值 * 相當於: * 當前root.val+root的兩個子點不搶 * root.val+nR[root.left]nR[root.right] * 字典2: **nR[n]** * 不搶該root,可得到最大值 * 相當於: * 不搶當前root.val,且對於其root的左右子分別可以選擇搶or不搶 * nR[root]=max(Ro[root.left], nR[root.left])+max(Ro[root.right], nR[root.right]) ## Python: ``` python= from collections import defaultdict class TreeNode(): def __init__(self,val=0,left=None,right=None): self.val=val self.left=left self.right=right def insertLeft(self,node): if self.left==None: self.left=TreeNode(node) else: self.left.insertLeft(node) def insertRight(self,node): if self.right==None: self.right=TreeNode(node) else: self.right.insertRight(node) def printTree(self): root=self stack=[root] res=[] while stack: root=stack.pop(0) res.append(root.val) if root.left: stack.append(root.left) if root.right: stack.append(root.right) print(res) # dp+dfs time:O(n) class Solution(object): def rob(self, root): """ :type root: TreeNode :rtype: int """ Ro=defaultdict(int) #搶 defaultdict(int)初始為0 就算是map[None]一樣是0 nR=defaultdict(int) #不搶 self.dfs(root,Ro,nR) return max(Ro[root],nR[root]) def dfs(self,root,Ro,nR): if not root: return self.dfs(root.left,Ro,nR) self.dfs(root.right,Ro,nR) Ro[root]=root.val+nR[root.left]+nR[root.right] nR[root]=max(Ro[root.left],nR[root.left])+max(Ro[root.right],nR[root.right]) root=TreeNode(3) root.insertLeft(2) root.insertRight(3) root.left.insertRight(3) root.right.insertRight(1) root.printTree() result=Solution() ans=result.rob(root) print(ans) ``` ## C++: ``` cpp= /** * 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: int rob(TreeNode* root) { dfs(root); return max(Ro[root], nR[root]); } void dfs(TreeNode* root){ if (!root) return; dfs(root->left); dfs(root->right); Ro[root]= root->val+ nR[root->left]+ nR[root->right]; nR[root]= max(Ro[root->left], nR[root->left])+ max(Ro[root->right], nR[root->right]); } private: unordered_map<TreeNode* ,int> Ro, nR; }; ```