题目地址:
https://leetcode.com/problems/maximum-sum-bst-in-binary-tree/
给定一棵二叉树,求其数值总和最大的二叉搜索树的数值总和。空树也算一棵BST。
思路是分治。要求每次DFS的时候返回当前子树是否是一棵BST,数值总和,最小值和最大值。设 f [ x ] = { b , s , m , M } f[x]=\{b, s, m, M\} f[x]={b,s,m,M},其中 b , s , m , M b,s,m,M b,s,m,M分别是 x x x子树是否是BST,数值总和,最小值和最大值,设 x . l x.l x.l和 x . r x.r x.r分别是 x x x的左右子树,那么 f [ x ] . b f[x].b f[x].b取决于其左右子树是否null、其左右子树是否是BST、以及当前节点与左子树最大值和右子树最小值的情况,可以先递归求解左右子树之后,将 f [ x ] . b f[x].b f[x].b求出来,如果当前子树不是BST,那就可以直接返回了(因为该子树不会更新答案),否则说明当前是BST,根据左右子树情况再更新 f [ x ] . s , f [ x ] . m , f [ x ] . M f[x].s,f[x].m,f[x].M f[x].s,f[x].m,f[x].M,则有 f [ x ] . s = f [ x . l ] . s + f [ x . r ] . s + x f[x].s=f[x.l].s+f[x.r].s+x f[x].s=f[x.l].s+f[x.r].s+x, f [ x ] . m = f [ x . l ] . m f[x].m=f[x.l].m f[x].m=f[x.l].m, f [ x ] . M = f [ x . r ] . M f[x].M=f[x.r].M f[x].M=f[x.r].M,再用 f [ x ] . s f[x].s f[x].s来更新答案。代码如下:
public class Solution {
private int res;
public int maxSumBST(TreeNode root) {
dfs(root);
return res;
}
private int[] dfs(TreeNode cur) {
if (cur == null) {
return null;
}
// 递归求解左右子树的信息
int[] left = dfs(cur.left), right = dfs(cur.right);
int[] info = {1, cur.val, cur.val, cur.val};
// 判断一下cur子树是否是BST,如果不是,就不用再继续了,直接返回
if (left != null && (left[3] >= cur.val || left[0] == 0) || right != null && (right[2] <= cur.val || right[0] == 0)) {
info[0] = 0;
return info;
}
// 否则cur子树是BST,更新其信息
info[1] += (left != null ? left[1] : 0) + (right != null ? right[1] : 0);
if (left != null) {
info[2] = left[2];
}
if (right != null) {
info[3] = right[3];
}
// 由于cur子树是BST,所以用其数值总和更新答案
res = Math.max(res, info[1]);
return info;
}
}
class TreeNode {
int val;
TreeNode left, right;
public TreeNode(int val) {
this.val = val;
}
}
时间复杂度 O ( n ) O(n) O(n),空间 O ( h ) O(h) O(h)。
C++:
class Solution {
public:
struct Node {
int mi, ma, sum;
bool bin;
};
int res;
int maxSumBST(TreeNode* root) {
res = 0;
dfs(root);
return res;
}
Node dfs(TreeNode* cur) {
if (!cur) return {INT_MAX, INT_MIN, 0, true};
auto l = dfs(cur->left), r = dfs(cur->right);
int sum = cur->val + l.sum + r.sum;
Node t = {min(cur->val, l.mi), max(cur->val, r.ma), sum, false};
if (l.bin && r.bin && l.ma < cur->val && cur->val < r.mi) {
res = max(res, sum);
t.bin = true;
}
return t;
}
};
时空复杂度一样。