IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【LeetCode】最大 BST 子树(使用二叉树递归求解) -> 正文阅读

[数据结构与算法]【LeetCode】最大 BST 子树(使用二叉树递归求解)

333. 最大 BST 子树 - 力扣(LeetCode)

一、题目

给定一个二叉树,找到其中最大的二叉搜索树(BST)子树,其中最大指的是子树节点数最多的。

注意:

子树必须包含其所有后代。

示例 :

示例:

输入: [10,5,15,1,8,null,7]

   10 
   / \ 
  5  15 
 / \   \ 
1   8   7

输出: 3
解释: 高亮部分为最大的 BST 子树。
     返回值 3 在这个样例中为子树大小。

二、代码

// 提交如下的代码,可以直接通过
public static int largestBSTSubtree(TreeNode head) {
    // 如果一棵树为空树,则其最大二叉搜索子树就是0
    if (head == null) {
        return 0;
    }
    // 通过二叉树递归求解
    return process(head).maxBSTSubtreeSize;
}

// 信息类
public static class Info {
    // 当前树的最大二叉搜索子树大小
    public int maxBSTSubtreeSize;
    // 当前树的大小
    public int allSize;
    // 当前树的最大值
    public int max;
    // 当前树的最小值
    public int min;
    public Info(int m, int a, int ma, int mi) {
        maxBSTSubtreeSize = m;
        allSize = a;
        max = ma;
        min = mi;
    }
}

// 递归
public static Info process(TreeNode x) {
    // 这里如果是空的话,我们不好去设置空树的max和min值,因为可以无穷大或无穷小。所以这里我们就直接返回null,让上层去做处理
    if (x == null) {
        return null;
    }
    // 左右子树递归去得到相应的Info
    Info leftInfo = process(x.left);
    Info rightInfo = process(x.right);
    // 设置max、min、allSize初始值。
    int max = x.val;
    int min = x.val;
    int allSize = 1;
    // 在下面的过程中完成对null的处理
    // 如果左子树不为空,则取更新max、min、allSize的值
    if (leftInfo != null) {
        // 与左子树的最大值比较
        max = Math.max(leftInfo.max, max);
        // 与左子树的最小值比较
        min = Math.min(leftInfo.min, min);
        // 节点数累加左子树的节点数
        allSize += leftInfo.allSize;
    }
    // 右子树同理
    if (rightInfo != null) {
        max = Math.max(rightInfo.max, max);
        min = Math.min(rightInfo.min, min);
        allSize += rightInfo.allSize;
    }

    // 到这里,就将最大值,最小值,节点数三个数据都求出来了,下面再去求最大搜索二叉子树大小
	
    // 下面这是考虑三种情况,1、最大二叉搜索树在左子树中,2、最大二叉搜索树在右子树中,3、最大二叉搜索树就是其本身
    // 设置情况1的最大二叉搜索子树大小初始值
    int p1 = -1;
    // 直接获取左子树的最大二叉搜索子树大小
    if (leftInfo != null) {
        p1 = leftInfo.maxBSTSubtreeSize;
    }
    // 设置情况2的最大二叉搜索子树大小初始值
    int p2 = -1;
    // 直接获取右子树的最大二叉搜索子树大小
    if (rightInfo != null) {
        p2 = rightInfo.maxBSTSubtreeSize;
    }
    // 设置情况3的最大二叉搜索子树大小初始值
    int p3 = -1;
    // 这个情况的前提是当前树必须是一棵二叉搜索出才可以。所以先去判断这棵树是否是一颗二叉搜索树
    // 判断左子树是否是二叉搜索树   通过最大二叉搜索树大小是否等于左子树节点数判断
    boolean leftBST = leftInfo == null ? true : (leftInfo.maxBSTSubtreeSize == leftInfo.allSize);
    // 判断右子树是否是二叉搜索树
    boolean rightBST = rightInfo == null ? true : (rightInfo.maxBSTSubtreeSize == rightInfo.allSize);
    // 如果左右子树都是二叉搜索树,就在去判断x是否大于左子树最大值,是否小于右子树最小值,只要这些条件都符合,就说明这是一棵二叉搜索树
    if (leftBST && rightBST) {
        // x是否大于左子树最大值
        boolean leftMaxLessX = leftInfo == null ? true : (leftInfo.max < x.val);
        // x是否小于右子树最小值
        boolean rightMinMoreX = rightInfo == null ? true : (x.val < rightInfo.min);
        // 如果上述条件都成立,说明当前树是一颗搜索二叉树
        if (leftMaxLessX && rightMinMoreX) {
            // 下面就去计算当前二叉树的最大二叉搜索子树大小,也就是计算当前二叉树的节点个数
            // 这里仍然要记得判断空树
            int leftSize = leftInfo == null ? 0 : leftInfo.allSize;
            int rightSize = rightInfo == null ? 0 : rightInfo.allSize;
            
            // 左右子树节点数加和 + 1
            p3 = leftSize + rightSize + 1;
        }
    }
    // 最后比较p1、p2、p3大小,找出最大的一个就是当前树的最大二叉搜索树的大小,再把其他的相关信息向上返回
    return new Info(Math.max(p1, Math.max(p2, p3)), allSize, max, min);
}

三、解题思路?

1、首先根据题意,找到目标。这道题就是找到以X为根结点的二叉树中最大的二叉搜索子树的大小。

2、根据我们的目标,分析所有的可能性。

  1. 和X无关,即X并不是一颗二叉搜索树,也就是说以X为根的树的最大二叉搜索子树在其左右子树中,并不以X节点为头。这种情况下有两种可能:
    • 以X为根节点的树的最大二叉搜索子树在其左子树中,也就是说以X为根节点的树的最大二叉搜索子树大小就是其左子树的最大二叉搜索子树大小。
    • 以X为根节点的树的最大二叉搜索子树在其右子树中,也就是说以X为根节点的树的最大二叉搜索子树大小就是其右子树的最大二叉搜索子树大小。
  2. 和X有关,即X是一颗二叉搜索树,也就是说以X为根的树的最大二叉搜索子树就是其本身,以X节点为头。所以最大的二叉搜索子树的大小就是以X为根节点的二叉树的节点数。这种情况,只有当以X为根节点的二叉树是一颗搜索二叉树才会成立,那么什么情况下它才能是搜索二叉树呢,下面我们列出所需要的所有条件:
    1. X树的左子树必须是搜索二叉树,X的右子树必须是搜索二叉树
    2. X要大于X左子树的max值,X要小于X右子树的min值

满足这两个条件我们就能确定X就是一棵搜索二叉树了,那么如果想要求X最大二叉搜索子树的大小,就是求X树本身的大小,那么就需要知道X的左右子树的大小才可以。

3、依照2找出来的所有可能性,我们就能知道想要得到最后的大小结果,到底需要左右子树提供给我们哪些信息,根据这些信息来设计我们的递归传递的信息类Info。

根据可能1),如果想要知道最大二叉搜索子树大小,就需要知道其左右子树的最大二叉搜索子树的大小,所以我们需要每一个树的最大二叉搜索子树大小

根据可能2),我们需要先判断X树是不是二叉搜索树,需要的信息就有,左右子树是否为搜索二叉树,左子树的max值和右子树的min值,这里因为左右子树要求的树不同(一个max,一个min),所以直接求全集。所以就需要每棵树是否为二叉搜索树每棵树的最大值max和最小值min

然后可能2)判断了X是二叉搜索子树之后,如果想得到最大二叉搜索子树的大小,就需要知道X树的大小,想知道X树的大小,就需要通过其左右子树的大小和 + 1得到,那么就需要其左右子树的大小,所以我们还需要每棵树的大小

综上所述,我们需要在Info中存储的信息有每一个树的最大二叉搜索子树大小、每棵树是否为二叉搜索树、每棵树的最大值max和最小值min、每棵树的大小。并且我们可以对Info做一些简化,原则就是看哪些信息可以通过其他的信息推导出来,这样的就可以省略掉。当一棵树是二叉搜索树时,那么其最大二叉搜索子树大小就等于它本身的大小,所以每棵树是否为二叉搜索树就可以通过每棵树的最大二叉搜索子树大小和每棵树大小是否相等来推导出来,每棵树是否为二叉搜索树这个信息就可以省略掉。

最终,我们就需要向Info中存储每一个树的最大二叉搜索子树大小、每棵树的最大值max和最小值min、每棵树的大小 这四个信息

4、利用左右子树传递上来的数据,去计算当前树的这些数据。知道了我们要在每一层递回向上返回哪些数据,剩下的要做的就是用代码去计算出这些数据的值,生成Info对象即可。就根据每一个值得特性,利用其左右子树传递上来的数据,来计算出当前树的这四个数据。

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-06-26 17:03:41  更:2022-06-26 17:05:19 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 23:32:25-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码