337. 打家劫舍 III
在上次打劫完一条街道之后和一圈房屋后,小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为“根”。 除了“根”之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果两个直接相连的房子在同一天晚上被打劫,房屋将自动报警。
计算在不触动警报的情况下,小偷一晚能够盗取的最高金额。
示例 1:
输入: [3,2,3,null,3,null,1]
3
/
2 3
3 1
输出: 7
解释: 小偷一晚能够盗取的最高金额 = 3 + 3 + 1 = 7.
示例 2:
输入: [3,4,5,1,3,null,1]
3
/
4 5
/
1 3 1
输出: 9
解释: 小偷一晚能够盗取的最高金额 = 4 + 5 = 9.
未优化
1 class Solution { 2 public: 3 int rob(TreeNode* root) { 4 if(root==NULL) return 0; 5 if(root->left==NULL&&root->right==NULL) return root->val; 6 else { 7 //这样一句话写下来,可能有空的,无法进行继续,比如 root->left=null, 则root->left->left报错 8 // return max(rob(root->left)+rob(root->right), root->val+rob(root->left->left)+rob(root->left->right)+rob(root->right->left)+rob(root->right->right)); 9 int ls=0,ls1=0,ls2=0,lr=0,lr1=0,lr2=0; 10 if(root->left!=NULL){ 11 if(root->left->left!=NULL){ 12 ls1=rob(root->left->left); 13 } 14 if(root->left->right!=NULL){ 15 ls2=rob(root->left->right); 16 } 17 ls=rob(root->left); 18 } 19 if(root->right!=NULL){ 20 if(root->right->left!=NULL){ 21 lr1=rob(root->right->left); 22 } 23 if(root->right->right){ 24 lr2=rob(root->right->right); 25 } 26 lr=rob(root->right); 27 } 28 // rob 函数的返回值 代表 从当前根 往下走 所选房间的 最大值 ; 即 max( 左子树的返回值+右子树的返回值,根的值+左子树的左子树的返回值+左子树的右子树的返回值+右子树的左子树的返回值+右子树的右子树的返回值); 29 return max(ls+lr,root->val+ls1+ls2 + lr1+lr2 ); 30 } 31 } 32 };
记忆化存储-优化
1 class Solution { 2 public: 3 map<TreeNode*,int> mp; 4 int rob(TreeNode* root) { 5 if(root==NULL) return 0; 6 if(mp[root]) return mp[root]; 7 // if(root->left==NULL&&root->right==NULL) return root->val;不需要,写了也对 8 else { 9 //抢左右子树的子树 10 int lss= root->left==NULL?0:rob(root->left->left)+rob(root->left->right); 11 int lrs=root->right==NULL?0:rob(root->right->left)+rob(root->right->right); 12 //抢左右子树 13 int sum=rob(root->left)+rob(root->right); 14 //算出最大值 15 int val=max(sum,root->val+lss+lrs); 16 //记忆化存储 17 mp[root]=val; 18 return val; 19 20 } 21 } 22 };
1 class Solution { 2 public: 3 //[0] 表示不抢 root 的话,得到的最大钱数 4 //[1] 表示抢 root 的话,得到的最大钱数 5 vector<int> dfs(TreeNode* root){ 6 if(root==NULL) return {0,0}; 7 vector<int>left=dfs(root->left); 8 vector<int>right=dfs(root->right); 9 int sum=root->val+left[0]+right[0];//抢,则左右子树不能抢 10 int Nsum=max(left[0],left[1])+max(right[0],right[1]);//不抢,下家可抢可不抢 11 return {Nsum,sum}; 12 } 13 int rob(TreeNode* root) { 14 vector<int> res=dfs(root); 15 return max(res[0], res[1]); 16 } 17 };