【Leetcode】333. Largest BST Subtree

题目地址:

https://leetcode.com/problems/largest-bst-subtree/

给定一个二叉树, 求其最大二叉搜索子树的节点个数。

思路是分治。在分治DFS返回的时候,要把当前节点为树根的子树是否是BST、有多少个节点、最大值、最小值四个信息都要返回给递归的上层。前两个信息可以捏再一起返回,例如,可以用 − 1 -1 1代表不是BST, 0 0 0代表是空树,正整数代表节点个数。这样判断一个节点为根的子树是否是BST就可以这样判断:
1、先递归搜集左右子树的信息;
2、如果左右子树有一个不是BST,则本树也不是BST,返回 ( − 1 , 0 , 0 ) (-1,0,0) (1,0,0)给上层,这里一旦发现不是BST,则不用返回最大最小值了,因为用不到;
3、如果左右子树都是BST,接下来就看左右子树是否可以接到本节点上。如果左子树为空或者左子树最大值小于当前节点,并且右子树为空或者右子树最小值大于当前节点,那么左右子树都可以接到本节点上,产生一棵更大的BST,此时就可以得到本节点BST的节点个数(等于 1 1 1加上左右子树的节点个数),也可以得到本节点BST的最大和最小值,用本节点BST的节点个数更新最终答案,然后返回给上层;
4、如果两个子树有其中一棵接不上去,则说明本节点的树不是BST,返回 ( − 1 , 0 , 0 ) (-1,0,0) (1,0,0)给上层。

代码如下:

/**
 * 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 largestBSTSubtree(TreeNode* root) {
    int res = 0;
    dfs(root, res);
    return res;
  }

  struct Node {
    int cnt, m, M;
  };

  Node dfs(auto cur, int& res) {
    if (!cur) return {0, 0, 0};
    auto l = dfs(cur->left, res), r = dfs(cur->right, res);
    // 如果左右子树其中一个不是BST,则直接标记-1返回
    if (!~l.cnt || !~r.cnt) return {-1, 0, 0};
    // 如果左右子树都能接到cur上,就更新最终答案
    if ((!cur->left || cur->val > l.M) && (!cur->right || cur->val < r.m)) {
      res = max(res, 1 + l.cnt + r.cnt);
      int m, M;
      m = M = cur->val;
      if (cur->left) m = l.m;
      if (cur->right) M = r.M;
      return {1 + l.cnt + r.cnt, m, M};
    }
    // 到这一步说明左右子树其中一个不能接到cur上,即cur子树不是BST,标记-1返回
    return {-1, 0, 0};
  }
};

时间复杂度 O ( n ) O(n) O(n),空间 O ( h ) O(h) O(h)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值