48
48
49
49
<!-- 这里可写通用的实现逻辑 -->
50
50
51
- 记忆化搜索。
51
+ ** 方法一:树形 DP**
52
+
53
+ 我们定义一个函数 $dfs(root)$,表示偷取以 $root$ 为根的二叉树的最大金额。该函数返回一个二元组 $(a, b)$,其中 $a$ 表示偷取 $root$ 节点时能得到的最大金额,而 $b$ 表示不偷取 $root$ 节点时能得到的最大金额。
54
+
55
+ 函数 $dfs(root)$ 的计算过程如下:
56
+
57
+ 如果 $root$ 为空,那么显然有 $dfs(root) = (0, 0)$。
58
+
59
+ 否则,我们首先计算出左右子节点的结果,即 $dfs(root.left)$ 和 $dfs(root.right)$,这样就得到了两对值 $(l_a, l_b)$ 以及 $(r_a, r_b)$。对于 $dfs(root)$ 的结果,我们可以分为两种情况:
60
+
61
+ - 如果偷取 $root$ 节点,那么不能偷取其左右子节点,结果为 $root.val + l_b + r_b$;
62
+ - 如果不偷取 $root$ 节点,那么可以偷取其左右子节点,结果为 $\max(l_a, l_b) + \max(r_a, r_b)$。
63
+
64
+ 在主函数中,我们可以直接返回 $dfs(root)$ 的较大值,即 $\max(dfs(root))$。
65
+
66
+ 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是二叉树的节点数。
52
67
53
68
<!-- tabs:start -->
54
69
64
79
# self.left = left
65
80
# self.right = right
66
81
class Solution :
67
- def rob (self , root : TreeNode) -> int :
68
- @cache
69
- def dfs (root ):
82
+ def rob (self , root : Optional[TreeNode]) -> int :
83
+ def dfs (root : Optional[TreeNode]) -> (int , int ):
70
84
if root is None :
71
- return 0
72
- if root.left is None and root.right is None :
73
- return root.val
74
- a = dfs(root.left) + dfs(root.right)
75
- b = root.val
76
- if root.left:
77
- b += dfs(root.left.left) + dfs(root.left.right)
78
- if root.right:
79
- b += dfs(root.right.left) + dfs(root.right.right)
80
- return max (a, b)
81
-
82
- return dfs(root)
85
+ return 0 , 0
86
+ la, lb = dfs(root.left)
87
+ ra, rb = dfs(root.right)
88
+ return root.val + lb + rb, max (la, lb) + max (ra, rb)
89
+
90
+ return max (dfs(root))
83
91
```
84
92
85
93
### ** Java**
@@ -103,31 +111,18 @@ class Solution:
103
111
* }
104
112
*/
105
113
class Solution {
106
- private Map<TreeNode , Integer > memo;
107
-
108
114
public int rob (TreeNode root ) {
109
- memo = new HashMap<> ( );
110
- return dfs(root );
115
+ int [] ans = dfs(root );
116
+ return Math . max(ans[ 0 ], ans[ 1 ] );
111
117
}
112
118
113
- private int dfs (TreeNode root ) {
119
+ private int [] dfs (TreeNode root ) {
114
120
if (root == null ) {
115
- return 0 ;
116
- }
117
- if (memo. containsKey(root)) {
118
- return memo. get(root);
119
- }
120
- int a = dfs(root. left) + dfs(root. right);
121
- int b = root. val;
122
- if (root. left != null ) {
123
- b += dfs(root. left. left) + dfs(root. left. right);
124
- }
125
- if (root. right != null ) {
126
- b += dfs(root. right. left) + dfs(root. right. right);
121
+ return new int [2 ];
127
122
}
128
- int res = Math . max(a, b );
129
- memo . put (root, res );
130
- return res ;
123
+ int [] l = dfs(root . left );
124
+ int [] r = dfs (root. right );
125
+ return new int [] {root . val + l[ 1 ] + r[ 1 ], Math . max(l[ 0 ], l[ 1 ]) + Math . max(r[ 0 ], r[ 1 ])} ;
131
126
}
132
127
}
133
128
```
@@ -148,22 +143,17 @@ class Solution {
148
143
*/
149
144
class Solution {
150
145
public:
151
- unordered_map<TreeNode* , int> memo;
152
-
153
146
int rob(TreeNode* root) {
154
- return dfs(root);
155
- }
156
-
157
- int dfs (TreeNode* root) {
158
- if (!root) return 0;
159
- if (memo.count(root)) return memo[ root] ;
160
- int a = dfs(root->left) + dfs(root->right);
161
- int b = root->val;
162
- if (root->left) b += dfs(root->left->left) + dfs(root->left->right);
163
- if (root->right) b += dfs(root->right->left) + dfs(root->right->right);
164
- int res = max(a, b);
165
- memo[ root] = res;
166
- return res;
147
+ function<pair<int, int>(TreeNode* )> dfs = [ &] (TreeNode* root) -> pair<int, int> {
148
+ if (!root) {
149
+ return make_pair(0, 0);
150
+ }
151
+ auto [ la, lb] = dfs(root->left);
152
+ auto [ ra, rb] = dfs(root->right);
153
+ return make_pair(root->val + lb + rb, max(la, lb) + max(ra, rb));
154
+ };
155
+ auto [ a, b] = dfs(root);
156
+ return max(a, b);
167
157
}
168
158
};
169
159
```
@@ -180,28 +170,17 @@ public:
180
170
* }
181
171
*/
182
172
func rob(root *TreeNode) int {
183
- memo := make(map[*TreeNode]int)
184
- var dfs func(root *TreeNode) int
185
- dfs = func(root *TreeNode) int {
173
+ var dfs func(*TreeNode) (int, int)
174
+ dfs = func(root *TreeNode) (int, int) {
186
175
if root == nil {
187
- return 0
176
+ return 0, 0
188
177
}
189
- if _, ok := memo[root]; ok {
190
- return memo[root]
191
- }
192
- a := dfs(root.Left) + dfs(root.Right)
193
- b := root.Val
194
- if root.Left != nil {
195
- b += dfs(root.Left.Left) + dfs(root.Left.Right)
196
- }
197
- if root.Right != nil {
198
- b += dfs(root.Right.Left) + dfs(root.Right.Right)
199
- }
200
- res := max(a, b)
201
- memo[root] = res
202
- return res
178
+ la, lb := dfs(root.Left)
179
+ ra, rb := dfs(root.Right)
180
+ return root.Val + lb + rb, max(la, lb) + max(ra, rb)
203
181
}
204
- return dfs(root)
182
+ a, b := dfs(root)
183
+ return max(a, b)
205
184
}
206
185
207
186
func max(a, b int) int {
@@ -212,6 +191,36 @@ func max(a, b int) int {
212
191
}
213
192
```
214
193
194
+ ### ** TypeScript**
195
+
196
+ ``` ts
197
+ /**
198
+ * Definition for a binary tree node.
199
+ * class TreeNode {
200
+ * val: number
201
+ * left: TreeNode | null
202
+ * right: TreeNode | null
203
+ * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
204
+ * this.val = (val===undefined ? 0 : val)
205
+ * this.left = (left===undefined ? null : left)
206
+ * this.right = (right===undefined ? null : right)
207
+ * }
208
+ * }
209
+ */
210
+
211
+ function rob(root : TreeNode | null ): number {
212
+ const dfs = (root : TreeNode | null ): [number , number ] => {
213
+ if (! root ) {
214
+ return [0 , 0 ];
215
+ }
216
+ const [la, lb] = dfs (root .left );
217
+ const [ra, rb] = dfs (root .right );
218
+ return [root .val + lb + rb , Math .max (la , lb ) + Math .max (ra , rb )];
219
+ };
220
+ return Math .max (... dfs (root ));
221
+ }
222
+ ```
223
+
215
224
### ** ...**
216
225
217
226
```
0 commit comments