LeetCode总结 -- 树的求和篇

树的求和属于树的题目中比较常见的,因为可以有几种变体,灵活度比较高,也可以考察到对于树的数据结构和递归的理解。一般来说这些题目就不用考虑非递归的解法了(虽然其实道理是跟LeetCode总结 -- 树的遍历篇一样的,只要掌握了应该没问题哈)。 LeetCode中关于树的求和有以下题目:
Path Sum
Path Sum II
Sum Root to Leaf Numbers
Binary Tree Maximum Path Sum

我们先来看看最常见的题目Path Sum。这道题是判断是否存在从根到叶子的路径和跟给定sum相同。树的题目基本都是用递归来解决,主要考虑两个问题:

1)如何把问题分治成子问题给左子树和右子树。这里就是看看左子树和右子树有没有存在和是sum减去当前结点值得路径,只要有一个存在,那么当前结点就存在路径。

2)考虑结束条件是什么。这里的结束条件一个是如果当前节点是空的,则返回false。另一个如果是叶子,那么如果剩余的sum等于当前叶子的值,则找到满足条件的路径,返回true。

想清楚上面两个问题,那么实现起来就是一次树的遍历,按照刚才的分析用参数或者返回值传递需要维护的值,然后按照递归条件和结束条件进行返回即可。算法的时间复杂度是一次遍历O(n),空间复杂度是栈的大小O(logn)。

对于Path Sum II,其实思路和Path Sum是完全一样的,只是需要输出所有路径,所以需要数据结构来维护路径,添加两个参数,一个用来维护走到当前结点的路径,一个用来保存满足条件的所有路径,思路上递归条件和结束条件是完全一致的,空间上这里会依赖于结果的数量了。

Sum Root to Leaf Numbers这道题多了两个变化,一个是每一个结点相当于位上的值,而不是本身有权重,不过其实没有太大变化,每一层乘以10加上自己的值就可以了。另一个变化就是要把所有路径累加起来,这个其实就是递归条件要进行调整,Path Sum中是判断左右子树有一个找到满足要求的路径即可,而这里则是把左右子树的结果相加返回作为当前节点的累加结果即可。

变化比较大而且有点难度的是Binary Tree Maximum Path Sum,这道题目的路径要求不再是从根到叶子的路径,这个题目是把树完全看成一个无向图,然后寻找其中的路径。想起来就觉得比上面那种麻烦许多,不过仔细考虑会发现还是有章可循的,找到一个根节点最大路径,无非就是找到左子树最大路径,加上自己的值,再加上右子树的最大路径(这里左右子树的路径有可能不取,如果小于0的话)。我们要做的事情就是对于每个结点都做一次上面说的这个累加。而左子树最大路径和右子树最大路径跟Path Sum II思路是比较类似的,虽然不一定要到叶子节点,不过标准也很简单,有大于0的就取,如果走下去路径和小于0那么就不取。从分治的角度来看,左右子树的最大路径就是取自己的值加上Max(0,左子树最大路径,右子树最大路径)。这么一想也就不用考虑那么多细节了。而通过当前节点的最长路径则是自己的值+Max(0,左子树最大路径)+Max(0,右子树最大路径)。所以整个算法就是维护这两个量,一个是自己加上左或者右子树最大路径作为它的父节点考虑的中间量,另一个就是自己加上左再加上右作为自己最大路径。具体的实现可以参见Binary Tree Maximum Path Sum

这篇总结主要讲了LeetCode中关于树的求和的题目。总体来说,求和路径有以下三种:(1)根到叶子结点的路径;(2)父结点沿着子结点往下的路径;(3)任意结点到任意结点(也就是看成无向图)。这几种路径方式在面试中经常灵活变化,不同的路径方式处理题目的方法也会略有不同,不过最复杂也就是Binary Tree Maximum Path Sum这种路径方式,只要考虑清楚仍然是一次递归遍历的问题哈。

时间: 2024-10-12 21:38:51

LeetCode总结 -- 树的求和篇的相关文章

LeetCode总结 -- 树的构造篇

这篇总结主要介绍树中比较常见的一类题型--树的构造.其实本质还是用递归的手法来实现,但是这类题目有一个特点,就是它是构建一棵树,而不是给定一棵树,然后进行遍历,所以实现起来思路上有点逆向,还是要练习一下.LeetCode中关于树的构造的题目有以下几道:Convert Sorted Array to Binary Search TreeConvert Sorted List to Binary Search TreeConstruct Binary Tree from Preorder and I

HDU4027 Can you answer these queries 线段树区间求和+剪枝

给了你n,然后n个数字在一个数组中,接下来m个询问,每个询问三个数字 t,x,y,若t==0,那么修改区间[x,y]的每一个值,变为原来每个位置上的数 开根号取整,若t==1,那么对区间[x,y]求和 由于n,m,很大,所以树状数组铁定超时,若直接用线段树来做区间修改,那么也是超时,这类题目没别的方法了,静心剪枝,发现题目给的数据范围为2^63,有没有发现,2^63开根号 绝对不需要开10次,就能到1,到1以后就不需要再开了,意思就是若有某个区间[x,y]每一个点的值都为1时,这一段区间事实上是

HDU 4027 Can you answer these queries? (线段树区间求和)

Can you answer these queries? Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)Total Submission(s): 12290    Accepted Submission(s): 2912 Problem Description A lot of battleships of evil are arranged in a line before

POJ 3468 线段树区间求和

线段树区间求和树节点不能只存和,只存和,会导致每次加数的时候都要更新到叶子节点,速度太慢(O(nlogn)).所以我们要存两个量,一个是原来的和nSum,一个是累加的增量Inc. 在增加时,如果要加的区间正好覆盖一个节点,则增加其节点的Inc值,不再往下走,否则要更新nSum(加上本次增量),再将增量往下传,这样更新的复杂度就是O(log(n)). 在查询时,如果待查区间不是正好覆盖一个节点,就将节点的Inc往下带,然后将Inc清0,接下来再往下查询. Inc往下带的过程也是区间分解的过程,复杂

POJ 2823 Sliding Window 线段树区间求和问题

题目链接 线段树区间求和问题,维护一个最大值一个最小值即可,线段树要用C++交才能过. 注意这道题不是求三个数的最大值最小值,是求k个的. 还有一种做法是单调队列,耗时更少. #include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> #define N 1000005 using namespace std; int

线段树 区间求和 poj 3468 A Simple Problem with Integers

题意: 给n个整数,求两种操作:1.给一个区间的数都加上一个数 2.查询一个区间的数的和  ,输出每次查询的结果 线段树区间求和,注意点: 1.使用lazy操作pushdown的时候,应该是子节点的lazy值加上父节点的lazy值,而不是直接赋值成父节点的lazy值,因为子节点可能之前也被操作过 2.节点的sum求和的时候应该加上区间的和(虽然直接加上修改值也能过样例TAT) 3.sum应该用long long 代码: #include <cstdlib> #include <cctyp

【LeetCode】树(共94题)

[94]Binary Tree Inorder Traversal [95]Unique Binary Search Trees II (2018年11月14日,算法群) 给了一个 n,返回结点是 1 - n 的所有形态的BST. 题解:枚举每个根节点 r, 然后递归的生成左右子树的所有集合,然后做笛卡尔积. 1 /** 2 * Definition for a binary tree node. 3 * struct TreeNode { 4 * int val; 5 * TreeNode *

平衡二叉树,AVL树之代码篇

看完了第一篇博客,相信大家对于平衡二叉树的插入调整以及删除调整已经有了一定的了解,下面,我们开始介绍代码部分. 首先,再次提一下使用的结构定义 1 typedef char KeyType; //关键字 2 typedef struct MyRcdType //记录 3 { 4 KeyType key; 5 }RcdType,*RcdArr; 6 typedef enum MyBFStatus //为了方便平衡因子的赋值,这里进行枚举 7 { //RH,EH,LH分别表示右子树较高,左右子树等高

平衡二叉树,AVL树之图解篇

学习过了二叉查找树,想必大家有遇到一个问题.例如,将一个数组{1,2,3,4}依次插入树的时候,形成了图1的情况.有建立树与没建立树对于数据的增删查改已经没有了任何帮助,反而增添了维护的成本.而只有建立的树如图2,才能够最大地体现二叉树的优点.            在上述的例子中,图2就是一棵平衡二叉树.科学家们提出平衡二叉树,就是为了让树的查找性能得到最大的体现(至少我是这样理解的,欢迎批评改正).下面进入今天的正题,平衡二叉树. AVL的定义 平衡二叉查找树:简称平衡二叉树.由前苏联的数学