LC-1080. 根到叶路径上的不足节点(递归DFS)

news/2024/11/17 0:48:59/

1080. 根到叶路径上的不足节点

难度中等126

给你二叉树的根节点 root 和一个整数 limit ,请你同时删除树中所有 不足节点 ,并返回最终二叉树的根节点。

假如通过节点 node 的每种可能的 “根-叶” 路径上值的总和全都小于给定的 limit,则该节点被称之为 不足节点 ,需要被删除。

叶子节点,就是没有子节点的节点。

示例 1:

img

输入:root = [1,2,3,4,-99,-99,7,8,9,-99,-99,12,13,-99,14], limit = 1
输出:[1,2,3,4,null,null,7,8,9,null,14]

示例 2:

img

输入:root = [5,4,8,11,null,17,4,7,1,null,null,5,3], limit = 22
输出:[5,4,8,11,null,17,4,7,null,null,null,5]

示例 3:

img

输入:root = [1,2,-3,-5,null,4,null], limit = -1
输出:[1,null,-3,4]

提示:

  • 树中节点数目在范围 [1, 5000]
  • -105 <= Node.val <= 105
  • -109 <= limit <= 109

递归

https://leetcode.cn/problems/insufficient-nodes-in-root-to-leaf-paths/solution/python3-di-gui-xiang-jie-1080-gen-dao-xi-cc4a/

递归的过程包含两部分,一部分是向下走的“递下去”的过程,另一部分是从终点想回走的“归上来”的过程。

在你的递归函数中:

调用下一个递归函数之前,都是在为“递下去”做准备,即在“递下去”之前执行;

而在调用递归函数之后,此时操作的所有代码均为“归上来”之后执行。

以上两点是递归最重要的两部分,只有理解了这两部分,在写代码的时候才能想清楚,才能知道某些操作应该放到什么位置。

备注:递归只有在处理(递下去)的问题时,才可以转化为迭代。处理(归上来)问题时,是无法转化为迭代的。

思路

理解了上面的递归,再来看这个题目就会容易很多了。

首先我们可以开一个Map,记录每个节点对应的经过该节点的所有路径和中的最大值。

因为我们是从上面根节点出发,所以传递路径和的过程应该放在“递下去”的过程中。

而如果我们只是向下传递路径和,那么只有叶子结点才是这条路径上的路径和,而其他非叶子节点都是不完整的路径和。

所以,我们还需要在递归执行到底下,准备返回时,将叶子节点的值传上来,使得每个非叶子节点的路径和得以完整。这时候我们再去选一个左右节点传上来的路径和的最大值即可。

当然,上一段的将叶子节点的值传上来这一操作是放在归上来的位置,这显而易见。

当我们归上来到该节点时,那么就证明递归已经从下面上来了,准备继续向上走了。那此时该节点左右子树的所有值都是已经计算完成的。这时候就可以根据题意判断删除「不足节点」了。

总结一下,在一个递归函数中,顺序如下:

  1. 向下传递该节点的值(前缀和思想);
  2. 执行递归函数;
  3. 向上传递叶子节点的路径和,并取左右子树中路径和最大的那个;
  4. 根据题意判断删除「不足节点」;
class Solution {Map<TreeNode, Integer> vals;int limit;public TreeNode sufficientSubset(TreeNode root, int limit) {this.limit = limit;TreeNode dummy = new TreeNode(0, root, null);// 记录每个节点对应的经过该节点的所有路径和中的最大值vals = new HashMap<>();dfs(dummy);return dummy.left;}public int dfs(TreeNode node){// 判断边界if(node == null) return Integer.MIN_VALUE;// 向下递归“递下去”,将自身值传递下去vals.put(node, vals.getOrDefault(node, 0) + node.val);if(node.left != null)vals.put(node.left, vals.getOrDefault(node.left, 0) + vals.get(node));if(node.right != null)vals.put(node.right, vals.getOrDefault(node.right, 0) + vals.get(node));// 只要当前节点不是叶子节点,vals[node]就是一个不完全的路径和// 需要从递归“归上来”的值中去选最大的if(node.left != null || node.right != null)vals.put(node, Math.max(dfs(node.left), dfs(node.right)));// 走到这里证明已经从下面归上来走到这里了,下面的所有值都已计算完成// 删除该删除的子节点即可if(node.left != null && vals.get(node.left) < limit)node.left = null;if(node.right != null && vals.get(node.right) < limit)node.right = null;return vals.get(node);}
}

简洁DFS

class Solution {public TreeNode sufficientSubset(TreeNode root, int limit) {limit -= root.val;if(root.left == root.right) // root是叶子// 如果 limit > 0 说明从根到叶子的路径和小于 limit,删除叶子,否则不删除return limit > 0 ? null : root;if(root.left != null) root.left = sufficientSubset(root.left, limit);if(root.right != null) root.right = sufficientSubset(root.right, limit);// 如果儿子都被删除,就删 root,否则不删 rootreturn root.left == null && root.right == null ? null : root;}
}

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

相关文章

SARscape连接图编辑(ConnectGraph)

SARscape连接图编辑ConnectGraph 0 连接图是什么1 什么时候需要编辑连接图2 连接图编辑步骤 0 连接图是什么 连接图ConnectGraph就是差分干涉数据对的关系图。 在SARscape中进行干涉叠加Interferometric Stacking处理&#xff0c;常见的包括PS和SBAS。 首先就要根据数据的空间…

Redis底层原理深入学习

一、基本类型及底层实现 1.String 1&#xff09;使用场景&#xff1a;简单字符串存储、分布式锁、计数器、全局唯一ID 2&#xff09;数据结构&#xff1a;C语言中String用char[]表示&#xff0c;源码中用SDS封装char[]&#xff0c;这是Redis存储的最小单元&#xff0c;一个SD…

Filter详解

Filter是什么&#xff1a; Filter表示过滤器&#xff0c;是Java Web三大组件之一&#xff08;Servlet、Filter、Listener&#xff09;。 过滤器可以把对资源的请求拦截下来&#xff0c;从而实现一些特殊的功能。 过滤器一般完成一些通用的操作&#xff0c;比如&#xff1a;权…

Nginx配置文件

四.Nginx配置 1.位置 /usr/local/nginx/conf/nginx.conf2.内容 Nginx的主配置文件是nginx.conf&#xff0c;这个配置文件一共由三部分组成&#xff0c;分别为全局块、events块和http块。在http块中&#xff0c;又包含http全局块、多个server块。每个server块中&#xff0c;可…

【Jasypt】Spring Boot 配置文件加解密 Jasypt 配置文件加密

Spring Boot 配置文件加解密 一、Jasypt简介二、集成方法2.1 方式一2.2 方式二2.3 方式三 三、Springboot整合Jasypt实战3.1 引入依赖3.2 编写配置类&#xff0c;配置相关信息3.3 使用Jasypt对数据库密码加密&#xff0c;并替换明文3.4 查看执行结果 四、拓展4.1 关于加解密秘钥…

java基础入门-14-【集合(泛型Set数据结构)】

Java基础入门-14-【集合(泛型&Set&数据结构)】 23、集合(泛型&Set&数据结构)1.泛型1.1 泛型概述1.2 泛型的好处1.3 泛型的细节1.4 代码案例1.5 泛型可以在很多地方进行定义1.6 泛型类1.7 泛型类的书写1.8 泛型方法1.9 泛型方法的练习1.10 泛型接口1.11 泛型…

图解LeetCode——138. 复制带随机指针的链表

一、题目 给你一个长度为 n 的链表&#xff0c;每个节点包含一个额外增加的随机指针 random &#xff0c;该指针可以指向链表中的任何节点或空节点。 构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成&#xff0c;其中每个新节点的值都设为其对应的原节点的值。…

从HelloWorld深入源码了解SpringSecurity底层逻辑

文章目录 一、环境搭建1、创建项目测试1.1、搭建基础项目1.2、整合Spring Security 二、实现原理1、Spring Security的实现原理1.1、Spring Security 如何完成认证和授权1.2、Security Filters 2、 Spring Security默认配置和如何自定义配置 三、整个HelloWorld的流程分析三、H…