|
73 | 73 |
|
74 | 74 | <!-- 这里可写通用的实现逻辑 -->
|
75 | 75 |
|
| 76 | +**方法一:DFS** |
| 77 | + |
| 78 | +判断一棵树是否是二叉搜索树,需要满足以下四个条件: |
| 79 | + |
| 80 | +- 左子树是二叉搜索树; |
| 81 | +- 右子树是二叉搜索树; |
| 82 | +- 左子树的最大值小于根节点的值; |
| 83 | +- 右子树的最小值大于根节点的值。 |
| 84 | + |
| 85 | +因此,我们设计一个函数 $dfs(root)$,函数的返回值是一个四元组 $(bst, mi, mx, s)$,其中: |
| 86 | + |
| 87 | +- 数字 $bst$ 表示以 $root$ 为根的树是否是二叉搜索树。如果是二叉搜索树,则 $bst = 1$;否则 $bst = 0$; |
| 88 | +- 数字 $mi$ 表示以 $root$ 为根的树的最小值; |
| 89 | +- 数字 $mx$ 表示以 $root$ 为根的树的最大值; |
| 90 | +- 数字 $s$ 表示以 $root$ 为根的树的所有节点的和。 |
| 91 | + |
| 92 | +函数 $dfs(root)$ 的执行逻辑如下: |
| 93 | + |
| 94 | +如果 $root$ 为空节点,则返回 $(1, +\infty, -\infty, 0)$,表示空树是二叉搜索树,最小值和最大值分别为正无穷和负无穷,节点和为 $0$。 |
| 95 | + |
| 96 | +否则,递归计算 $root$ 的左子树和右子树,分别得到 $(lbst, lmi, lmx, ls)$ 和 $(rbst, rmi, rmx, rs)$,然后判断 $root$ 节点是否满足二叉搜索树的条件。 |
| 97 | + |
| 98 | +如果满足 $lbst = 1$ 且 $rbst = 1$ 且 $lmx \lt root.val \lt rmi$,则以 $root$ 为根的树是二叉搜索树,节点和 $s= ls + rs + root.val$。我们更新答案 $ans = \max(ans, s)$,并返回 $(1, \min(lmi, root.val), \max(rmx, root.val), s)$。 |
| 99 | + |
| 100 | +否则,以 $root$ 为根的树不是二叉搜索树,我们返回 $(0, 0, 0, 0)$。 |
| 101 | + |
| 102 | +我们在主函数中调用 $dfs(root)$,执行完毕后,答案即为 $ans$。 |
| 103 | + |
| 104 | +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是二叉树的节点数。 |
| 105 | + |
76 | 106 | <!-- tabs:start -->
|
77 | 107 |
|
78 | 108 | ### **Python3**
|
79 | 109 |
|
80 | 110 | <!-- 这里可写当前语言的特殊实现逻辑 -->
|
81 | 111 |
|
82 | 112 | ```python
|
83 |
| - |
| 113 | +# Definition for a binary tree node. |
| 114 | +# class TreeNode: |
| 115 | +# def __init__(self, val=0, left=None, right=None): |
| 116 | +# self.val = val |
| 117 | +# self.left = left |
| 118 | +# self.right = right |
| 119 | +class Solution: |
| 120 | + def maxSumBST(self, root: Optional[TreeNode]) -> int: |
| 121 | + def dfs(root: Optional[TreeNode]) -> tuple: |
| 122 | + if root is None: |
| 123 | + return 1, inf, -inf, 0 |
| 124 | + lbst, lmi, lmx, ls = dfs(root.left) |
| 125 | + rbst, rmi, rmx, rs = dfs(root.right) |
| 126 | + if lbst and rbst and lmx < root.val < rmi: |
| 127 | + nonlocal ans |
| 128 | + s = ls + rs + root.val |
| 129 | + ans = max(ans, s) |
| 130 | + return 1, min(lmi, root.val), max(rmx, root.val), s |
| 131 | + return 0, 0, 0, 0 |
| 132 | + |
| 133 | + ans = 0 |
| 134 | + dfs(root) |
| 135 | + return ans |
84 | 136 | ```
|
85 | 137 |
|
86 | 138 | ### **Java**
|
87 | 139 |
|
88 | 140 | <!-- 这里可写当前语言的特殊实现逻辑 -->
|
89 | 141 |
|
90 | 142 | ```java
|
| 143 | +/** |
| 144 | + * Definition for a binary tree node. |
| 145 | + * public class TreeNode { |
| 146 | + * int val; |
| 147 | + * TreeNode left; |
| 148 | + * TreeNode right; |
| 149 | + * TreeNode() {} |
| 150 | + * TreeNode(int val) { this.val = val; } |
| 151 | + * TreeNode(int val, TreeNode left, TreeNode right) { |
| 152 | + * this.val = val; |
| 153 | + * this.left = left; |
| 154 | + * this.right = right; |
| 155 | + * } |
| 156 | + * } |
| 157 | + */ |
| 158 | +class Solution { |
| 159 | + private int ans; |
| 160 | + private final int inf = 1 << 30; |
| 161 | + |
| 162 | + public int maxSumBST(TreeNode root) { |
| 163 | + dfs(root); |
| 164 | + return ans; |
| 165 | + } |
| 166 | + |
| 167 | + private int[] dfs(TreeNode root) { |
| 168 | + if (root == null) { |
| 169 | + return new int[] {1, inf, -inf, 0}; |
| 170 | + } |
| 171 | + var l = dfs(root.left); |
| 172 | + var r = dfs(root.right); |
| 173 | + int v = root.val; |
| 174 | + if (l[0] == 1 && r[0] == 1 && l[2] < v && r[1] > v) { |
| 175 | + int s = v + l[3] + r[3]; |
| 176 | + ans = Math.max(ans, s); |
| 177 | + return new int[] {1, Math.min(l[1], v), Math.max(r[2], v), s}; |
| 178 | + } |
| 179 | + return new int[4]; |
| 180 | + } |
| 181 | +} |
| 182 | +``` |
| 183 | + |
| 184 | +### **C++** |
| 185 | + |
| 186 | +```cpp |
| 187 | +/** |
| 188 | + * Definition for a binary tree node. |
| 189 | + * struct TreeNode { |
| 190 | + * int val; |
| 191 | + * TreeNode *left; |
| 192 | + * TreeNode *right; |
| 193 | + * TreeNode() : val(0), left(nullptr), right(nullptr) {} |
| 194 | + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} |
| 195 | + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} |
| 196 | + * }; |
| 197 | + */ |
| 198 | +class Solution { |
| 199 | +public: |
| 200 | + int maxSumBST(TreeNode* root) { |
| 201 | + int ans = 0; |
| 202 | + const int inf = 1 << 30; |
| 203 | + |
| 204 | + function<vector<int>(TreeNode*)> dfs = [&](TreeNode* root) { |
| 205 | + if (!root) { |
| 206 | + return vector<int>{1, inf, -inf, 0}; |
| 207 | + } |
| 208 | + auto l = dfs(root->left); |
| 209 | + auto r = dfs(root->right); |
| 210 | + int v = root->val; |
| 211 | + if (l[0] && r[0] && l[2] < v && v < r[1]) { |
| 212 | + int s = l[3] + r[3] + v; |
| 213 | + ans = max(ans, s); |
| 214 | + return vector<int>{1, min(l[1], v), max(r[2], v), s}; |
| 215 | + } |
| 216 | + return vector<int>(4); |
| 217 | + }; |
| 218 | + dfs(root); |
| 219 | + return ans; |
| 220 | + } |
| 221 | +}; |
| 222 | +``` |
| 223 | + |
| 224 | +### **Go** |
| 225 | + |
| 226 | +```go |
| 227 | +/** |
| 228 | + * Definition for a binary tree node. |
| 229 | + * type TreeNode struct { |
| 230 | + * Val int |
| 231 | + * Left *TreeNode |
| 232 | + * Right *TreeNode |
| 233 | + * } |
| 234 | + */ |
| 235 | +func maxSumBST(root *TreeNode) (ans int) { |
| 236 | + const inf = 1 << 30 |
| 237 | + var dfs func(root *TreeNode) [4]int |
| 238 | + dfs = func(root *TreeNode) [4]int { |
| 239 | + if root == nil { |
| 240 | + return [4]int{1, inf, -inf, 0} |
| 241 | + } |
| 242 | + l, r := dfs(root.Left), dfs(root.Right) |
| 243 | + if l[0] == 1 && r[0] == 1 && l[2] < root.Val && root.Val < r[1] { |
| 244 | + s := l[3] + r[3] + root.Val |
| 245 | + ans = max(ans, s) |
| 246 | + return [4]int{1, min(l[1], root.Val), max(r[2], root.Val), s} |
| 247 | + } |
| 248 | + return [4]int{} |
| 249 | + } |
| 250 | + dfs(root) |
| 251 | + return |
| 252 | +} |
| 253 | + |
| 254 | +func max(a, b int) int { |
| 255 | + if a > b { |
| 256 | + return a |
| 257 | + } |
| 258 | + return b |
| 259 | +} |
| 260 | + |
| 261 | +func min(a, b int) int { |
| 262 | + if a < b { |
| 263 | + return a |
| 264 | + } |
| 265 | + return b |
| 266 | +} |
| 267 | +``` |
91 | 268 |
|
| 269 | +### **TypeScript** |
| 270 | + |
| 271 | +```ts |
| 272 | +/** |
| 273 | + * Definition for a binary tree node. |
| 274 | + * class TreeNode { |
| 275 | + * val: number |
| 276 | + * left: TreeNode | null |
| 277 | + * right: TreeNode | null |
| 278 | + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { |
| 279 | + * this.val = (val===undefined ? 0 : val) |
| 280 | + * this.left = (left===undefined ? null : left) |
| 281 | + * this.right = (right===undefined ? null : right) |
| 282 | + * } |
| 283 | + * } |
| 284 | + */ |
| 285 | + |
| 286 | +function maxSumBST(root: TreeNode | null): number { |
| 287 | + const inf = 1 << 30; |
| 288 | + let ans = 0; |
| 289 | + const dfs = (root: TreeNode | null): [boolean, number, number, number] => { |
| 290 | + if (!root) { |
| 291 | + return [true, inf, -inf, 0]; |
| 292 | + } |
| 293 | + const [lbst, lmi, lmx, ls] = dfs(root.left); |
| 294 | + const [rbst, rmi, rmx, rs] = dfs(root.right); |
| 295 | + if (lbst && rbst && lmx < root.val && root.val < rmi) { |
| 296 | + const s = ls + rs + root.val; |
| 297 | + ans = Math.max(ans, s); |
| 298 | + return [true, Math.min(lmi, root.val), Math.max(rmx, root.val), s]; |
| 299 | + } |
| 300 | + return [false, 0, 0, 0]; |
| 301 | + }; |
| 302 | + dfs(root); |
| 303 | + return ans; |
| 304 | +} |
92 | 305 | ```
|
93 | 306 |
|
94 | 307 | ### **...**
|
|
0 commit comments