Blage's Coding Blage's Coding
Home
算法
  • 手写Spring
  • SSM
  • SpringBoot
  • JavaWeb
  • JAVA基础
  • 容器
  • Netty

    • IO模型
    • Netty初级
    • Netty原理
  • JVM
  • JUC
  • Redis基础
  • 源码分析
  • 实战应用
  • 单机缓存
  • MySQL

    • 基础部分
    • 实战与处理方案
    • 面试
  • ORM框架

    • Mybatis
    • Mybatis_Plus
  • SpringCloudAlibaba
  • MQ消息队列
  • Nginx
  • Elasticsearch
  • Gateway
  • Xxl-job
  • Feign
  • Eureka
  • 面试
  • 工具
  • 项目
  • 关于
🌏本站
🧸GitHub (opens new window)
Home
算法
  • 手写Spring
  • SSM
  • SpringBoot
  • JavaWeb
  • JAVA基础
  • 容器
  • Netty

    • IO模型
    • Netty初级
    • Netty原理
  • JVM
  • JUC
  • Redis基础
  • 源码分析
  • 实战应用
  • 单机缓存
  • MySQL

    • 基础部分
    • 实战与处理方案
    • 面试
  • ORM框架

    • Mybatis
    • Mybatis_Plus
  • SpringCloudAlibaba
  • MQ消息队列
  • Nginx
  • Elasticsearch
  • Gateway
  • Xxl-job
  • Feign
  • Eureka
  • 面试
  • 工具
  • 项目
  • 关于
🌏本站
🧸GitHub (opens new window)
  • 数组

  • 链表

  • 字符串

  • 二叉树

    • 102.二叉树的层序遍历
    • 103.二叉树的锯齿形层序遍历
    • 124.二叉树中的最大路径和
    • 236.二叉树的最近公共祖先
    • 105.从前序与中序遍历序列构造二叉树
    • 662.二叉树最大宽度
    • 1080. 根到叶路径上的不足节点
    • 101. 对称二叉树
    • 226. 翻转二叉树
    • 114. 二叉树展开为链表
    • 1110. 删点成林
    • 337. 打家劫舍 III
    • 979. 在二叉树中分配硬币
    • 222. 完全二叉树的节点个数
    • 513. 找树左下角的值
    • 968. 监控二叉树
    • 剑指offer34
    • 剑指 Offer 32 - III. 从上到下打印二叉树 III
    • 剑指 Offer 33. 二叉搜索树的后序遍历序列
    • 线索二叉树

    • 二叉搜索树

      • 98.验证二叉搜索树
      • 426.二叉搜索树与双向链表
      • 1373. 二叉搜索子树的最大键值和
        • 538. 把二叉搜索树转换为累加树
        • 501. 二叉搜索树中的众数
        • 1382. 将二叉搜索树变平衡
    • 动态规划

    • 深搜回溯

    • 数学贪心

    • 堆栈队列

    • 前缀和

    • 算法设计

    • 位运算

    • WA

    • 算法
    • 二叉树
    • 二叉搜索树
    phan
    2023-05-20
    目录

    1373. 二叉搜索子树的最大键值和

    # 1373. 二叉搜索子树的最大键值和

    DFS+后序遍历

    解题思路:最关键的地方在于二叉搜索树的判断采用什么算法进行验证,这决定着二叉树键值和的计算在什么时机。一般含有以下方法:98.验证二叉搜索树。包括后续遍历,和中序遍历,递归。

    这里得出一条最关键的经验,就是二叉搜索树用后续遍历+划分子树上下界的方法比较合适。

    # 中序遍历存在的问题

    前几遍都是采用中序遍历做的,因为二叉搜索树的中序遍历序列正好是一个有序数列,用一个last变量保存前一个节点的值,当前节点如果比前一个节点小,那么说明当前节点不符合二叉搜索树。

    但是中序遍历的做法有一个很大的问题在于,在比较时如果当前节点小于上一个节点值,仅仅只能说明以当前节点为根的树不是一颗搜索二叉树,但是这两个节点的相对位置并不能确定(当前节点和前一个节点谁是父亲谁是儿子,左子树还是右子树),而有些时候即使不满足大小规则也需要继续计算树的键值和(比如当前节点是前一个节点的右子树的最左节点)。因此使用last节点比较的结果中既包含了需要继续计算键值和的,也包含需要终止计算直接返回的,而无法进一步区分。因此中序遍历仅适合于判断是否满足搜索二叉树。

    # 上下界划分+DFS后序遍历

    解题的关键在于想明白什么情况下可以统计当前树的键值和,什么情况下需要直接退出返回。直接返回的情况一共包含四种:

    • 左子树不是一颗搜索二叉树
    • 右子树不是一颗搜索二叉树
    • 当前节点的值小于等于左子树的上界
    • 当前节点的值大于等于右子树的下界

    也就是说通过上下界方法,将两个节点不满足大小关系的情况,统一都在层数更高的那个节点检测出来,也就说交给父/祖先节点做大小判断。这样子的话即使是A儿子节点不满足B祖先节点的大小平衡,那么A节点可以继续计算C父节点的二叉搜索树的键值和,到B节点直接返回即可。

    因此每个节点递归遍历时,都需要返回以下几个参数:①以当前节点为根的树是否是二叉搜索树②当前节点为根的树的下界③当前节点为根的树的上界④当前节点为根的树的键值和

    # 细节

    有两个地方需要注意:

    • 叶子节点自成一颗二叉搜索树,需要和当前最大值进行比较
    • 左子树为空或者右子树为空的节点,其上下界需要设置为当前节点的值
    • 一定要遍历完左子树和右子树后,在进行统一的返回判断并退出
    class Solution {
        int maxSum=0;
    
        public int maxSumBST(TreeNode root) {
            dfs(root);
            return maxSum;
        }
        public int[] dfs(TreeNode root) {
            if(root.left==null&&root.right==null){
                maxSum=root.val>maxSum?root.val:maxSum;
                return new int[]{1,root.val,root.val,root.val};
            }
            int[] leftsum=new int[]{1,root.val,root.val,0};
            int[] rightsum=new int[]{1,root.val,root.val,0};
            boolean valid=true;
            if(root.left!=null){
                leftsum=dfs(root.left);
                if(root.val<=leftsum[2]||leftsum[0]==0)
                valid=false;
            }
            if(root.right!=null){
                rightsum=dfs(root.right);
                if(root.val>=rightsum[1]||rightsum[0]==0)
                valid=false;
            }
            //左右子树都执行完后再跳出
            if(!valid)
            return new int[]{0,0,0,0};
            
            int ans=root.val+leftsum[3]+rightsum[3];
            maxSum=ans>maxSum?ans:maxSum;
            return new int[]{1,leftsum[1],rightsum[2],ans};
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    编辑 (opens new window)
    #Leetcode#二叉树
    上次更新: 2023/12/15, 15:49:57
    426.二叉搜索树与双向链表
    538. 把二叉搜索树转换为累加树

    ← 426.二叉搜索树与双向链表 538. 把二叉搜索树转换为累加树→

    Theme by Vdoing | Copyright © 2023-2024 blageCoder
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式