求二叉树中最大的二叉搜索子树的头节点

news/2024/11/28 21:34:57/

求二叉树中最大的二叉搜索子树的头节点

作者:Grey

原文地址:

博客园:求二叉树中最大的二叉搜索子树的头节点

CSDN:求二叉树中最大的二叉搜索子树的头节点

题目描述

给定一棵二叉树的头节点head, 返回这颗二叉树中最大的二叉搜索子树的头节点。

暴力解法

定义递归函数

TreeNode maxSubBSTHead1(TreeNode head)

递归含义表示:以head为头的二叉树中最大的二叉搜索子树的头结点是什么。

接下来是 base case,

    if (head == null) {return null;}

定义一个辅助函数getBSTSize(head),这个函数表示:如果以head为头的树是二叉搜索树,则返回其大小,否则返回 0。

getBSTSize(head)的实现思路也比较简单,即通过中序遍历收集以 head 为头的树,如果这个树满足二叉搜索子树,则返回二叉搜索子树的大小,如果以 head 的头不是二叉搜索树,直接返回 0。

代码如下

  public static int getBSTSize(TreeNode head) {if (head == null) {return 0;}ArrayList<TreeNode> arr = new ArrayList<>();// 中序遍历收集以 head 为头的二叉树,存在数组中in(head, arr);for (int i = 1; i < arr.size(); i++) {if (arr.get(i).val <= arr.get(i - 1).val) {return 0;}}return arr.size();}

实现了如上方法,主函数直接做如下调用即可,代码说明见注释:

  public static TreeNode maxSubBSTHead1(TreeNode head) {if (head == null) {return null;}// 以 head 为头的二叉搜索子树大小不为0,说明head这就是最大的二叉搜索子树头!if (getBSTSize(head) != 0) {return head;}// 去左树上找哪个结点是最大二叉搜索子树的头结点TreeNode leftAns = maxSubBSTHead1(head.left);// 去右树上找哪个结点是最大二叉搜索子树的头结点TreeNode rightAns = maxSubBSTHead1(head.right);// 左右树哪个二叉搜索子树更大,就返回哪个结点return getBSTSize(leftAns) >= getBSTSize(rightAns) ? leftAns : rightAns;}

二叉树的递归套路

定义如下数据结构

  public static class Info {public TreeNode maxSubBSTHead;public int maxSubBSTSize;public int min;public int max;public Info(TreeNode h, int size, int mi, int ma) {maxSubBSTHead = h;maxSubBSTSize = size;min = mi;max = ma;}}

针对每一颗子树,都有如上结构信息,其中

maxSubBSTHead: 表示某个子树的最大二叉搜索子树的头结点

maxSubBSTSize: 表示某个结点如果是二叉搜索树,其大小为多少

min:表示以某个结点为头的树的最小值是多少

max:表示以某个结点为头的树的最大值是多少

接下来定义递归函数

Info process(TreeNode X)

以 X 为头的树,返回对应的 Info

接下来整理可能性

  1. 如果 X == null 则直接返回 null,即 base case;

  2. 接下来问左树要 Info 信息,再问右树要 Info 信息,整合成 head 的 info 信息,以代码注释来说明

// 问左树要信息Info leftInfo = process(X.left);// 问右树要信息Info rightInfo = process(X.right);int min = X.val;int max = X.val;TreeNode maxSubBSTHead = null;int maxSubBSTSize = 0;if (leftInfo != null) {// 左树信息不为 null// 则 head.val 和 左树的min PK,谁小谁是以head 为头的min 信息min = Math.min(min, leftInfo.min);// 则 head.val 和 左树的max PK,谁大谁是以head 为头的max 信息max = Math.max(max, leftInfo.max);// 以 head 为头的最大二叉搜索子树的头结点至少是leftInfo.maxSubBSTHeadmaxSubBSTHead = leftInfo.maxSubBSTHead;// 以 head 为头的最大二叉搜索子树的头结点大小至少是leftInfo.maxSubBSTSizemaxSubBSTSize = leftInfo.maxSubBSTSize;}if (rightInfo != null) {// 右树信息不为 null // 思路和 左树信息不为 null 一样min = Math.min(min, rightInfo.min);max = Math.max(max, rightInfo.max);if (rightInfo.maxSubBSTSize > maxSubBSTSize) {maxSubBSTHead = rightInfo.maxSubBSTHead;maxSubBSTSize = rightInfo.maxSubBSTSize;}}// 到了这一步,说明 leftInfo 和 rightInfo 至少有一个为 null// 不管哪个为null,如果要以 X 为最大二叉搜索子树的头结点,则需要满足以下条件// 1. leftInfo.maxSubBSTHead == X.left && leftInfo.max < X.val// 2. rightInfo.maxSubBSTHead == X.right && rightInfo.min > X.valif ((leftInfo == null || (leftInfo.maxSubBSTHead == X.left && leftInfo.max < X.val))&& (rightInfo == null || (rightInfo.maxSubBSTHead == X.right && rightInfo.min > X.val))) {maxSubBSTHead = X;maxSubBSTSize =(leftInfo == null ? 0 : leftInfo.maxSubBSTSize)+ (rightInfo == null ? 0 : rightInfo.maxSubBSTSize)+ 1;}return new Info(maxSubBSTHead, maxSubBSTSize, min, max);

两个思路完整代码如下(含测试代码)

import java.util.ArrayList;public class Code_MaxSubBSTHead {public static class TreeNode {public int val;public TreeNode left;public TreeNode right;public TreeNode(int data) {this.val = data;}}public static int getBSTSize(TreeNode head) {if (head == null) {return 0;}ArrayList<TreeNode> arr = new ArrayList<>();in(head, arr);for (int i = 1; i < arr.size(); i++) {if (arr.get(i).val <= arr.get(i - 1).val) {return 0;}}return arr.size();}public static void in(TreeNode head, ArrayList<TreeNode> arr) {if (head == null) {return;}in(head.left, arr);arr.add(head);in(head.right, arr);}public static TreeNode maxSubBSTHead1(TreeNode head) {if (head == null) {return null;}if (getBSTSize(head) != 0) {return head;}TreeNode leftAns = maxSubBSTHead1(head.left);TreeNode rightAns = maxSubBSTHead1(head.right);return getBSTSize(leftAns) >= getBSTSize(rightAns) ? leftAns : rightAns;}public static TreeNode maxSubBSTHead2(TreeNode head) {if (head == null) {return null;}return process(head).maxSubBSTHead;}// 每一棵子树public static class Info {public TreeNode maxSubBSTHead;public int maxSubBSTSize;public int min;public int max;public Info(TreeNode h, int size, int mi, int ma) {maxSubBSTHead = h;maxSubBSTSize = size;min = mi;max = ma;}}public static Info process(TreeNode X) {if (X == null) {return null;}Info leftInfo = process(X.left);Info rightInfo = process(X.right);int min = X.val;int max = X.val;TreeNode maxSubBSTHead = null;int maxSubBSTSize = 0;if (leftInfo != null) {min = Math.min(min, leftInfo.min);max = Math.max(max, leftInfo.max);maxSubBSTHead = leftInfo.maxSubBSTHead;maxSubBSTSize = leftInfo.maxSubBSTSize;}if (rightInfo != null) {min = Math.min(min, rightInfo.min);max = Math.max(max, rightInfo.max);if (rightInfo.maxSubBSTSize > maxSubBSTSize) {maxSubBSTHead = rightInfo.maxSubBSTHead;maxSubBSTSize = rightInfo.maxSubBSTSize;}}if ((leftInfo == null ? true : (leftInfo.maxSubBSTHead == X.left && leftInfo.max < X.val))&& (rightInfo == null? true: (rightInfo.maxSubBSTHead == X.right && rightInfo.min > X.val))) {maxSubBSTHead = X;maxSubBSTSize =(leftInfo == null ? 0 : leftInfo.maxSubBSTSize)+ (rightInfo == null ? 0 : rightInfo.maxSubBSTSize)+ 1;}return new Info(maxSubBSTHead, maxSubBSTSize, min, max);}// for testpublic static TreeNode generateRandomBST(int maxLevel, int maxValue) {return generate(1, maxLevel, maxValue);}// for testpublic static TreeNode generate(int level, int maxLevel, int maxValue) {if (level > maxLevel || Math.random() < 0.5) {return null;}TreeNode head = new TreeNode((int) (Math.random() * maxValue));head.left = generate(level + 1, maxLevel, maxValue);head.right = generate(level + 1, maxLevel, maxValue);return head;}public static void main(String[] args) {int maxLevel = 4;int maxValue = 100;int testTimes = 1000000;for (int i = 0; i < testTimes; i++) {TreeNode head = generateRandomBST(maxLevel, maxValue);if (maxSubBSTHead1(head) != maxSubBSTHead2(head)) {System.out.println("Oops!");}}System.out.println("finish!");}
}

更多

算法和数据结构笔记


http://www.ppmy.cn/news/1640.html

相关文章

对文本进行情感分析(分类)snownlp模块

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 对文本进行情感分析(分类) snownlp模块 选择题 对于以下python代码表述错误的一项是? from snownlp import SnowNLP myText我爱学python&#xff01; print("【显示】text"…

项目管理逻辑:日志\周报\月报, 一直要求写, 有用吗?

目录 1.公司管控项目: 2.什么是项目的生命周期? 3.项目管控举例 3.1装修项目阶段划分 3.2研发项目 4.控制项目的核心 1.公司管控项目: 写周报,日报,项目问题照样失控, 其实本质上的问题就是 我们没有如何设置好项目的阶段和项目的里程碑. 项目管理的五个阶段 2.什么是…

41岁了,我该何去何从?

大家好&#xff0c;我是记得诚。 很多新人很迷茫&#xff0c;我想说的是&#xff1a;人人都会迷茫&#xff0c;下面这个41岁的老大哥也迷茫了&#xff0c;很多时候选择真的是一个难题。 下面是对话&#xff0c;大家可以看看。 问&#xff1a; 您好&#xff0c;不好意思打扰…

JavaWeb--JDBC核心技术

JavaWeb--JDBC核心技术JDBC核心技术第1章&#xff1a;JDBC概述1.1 数据的持久化1.2 Java中的数据存储技术1.3 JDBC介绍1.4 JDBC体系结构1.5 JDBC程序编写步骤第2章&#xff1a;获取数据库连接2.1 要素一&#xff1a;Driver接口实现类2.1.1 Driver接口介绍2.1.2 加载与注册JDBC驱…

(一)LTspice简介

文章目录前言一、举例1.1、RC滤波1.2、仿真结果二、软件安装总结前言 LTspice是一款高性能SPICE仿真器软件&#xff0c;包括原理图捕获图形界面。可探测原理图以产生仿真结果&#xff0c;通过LTspice内置波形查看器轻松探索。与其他SPICE解决方案相比&#xff0c;LTspice的增强…

uImage的制作工具mkimage详解(源码编译、使用方法、添加的头解析、uImage的制作)

1、mkimage工具的源码 (1)mkimage是uboot下面的一个工具&#xff0c;用来将zImage制作成uImage&#xff0c;制作内核启动镜像(给zImage镜像添加64字节的头信息成uImage)&#xff1b; (2)mkimage的源码在"uboot/tool"目录下&#xff0c;在编译uboot时默认会编译出mkim…

前端环境变量及vite中本地环境配置实践

前言 前端在之前并没有工程化的概念&#xff0c;甚至开发环境、测试环境、生产环境全靠大家手动配置。 有了nodejs之后&#xff0c;环境变量 &#xff08;environment variables&#xff09;这个概念&#xff0c;便慢慢进入了前端的视野&#xff0c;方便了前端各种环境自动化…

免费查题接口

免费查题接口 本平台优点&#xff1a; 多题库查题、独立后台、响应速度快、全网平台可查、功能最全&#xff01; 1.想要给自己的公众号获得查题接口&#xff0c;只需要两步&#xff01; 2.题库&#xff1a; 查题校园题库&#xff1a;查题校园题库后台&#xff08;点击跳转&a…