二叉树与递归
递归思路
二叉树和递归。
二叉树问题的思考方式
为什么需要使用递归
为什么这种写法一定能算出正确答案
计算机如何执行递归
另一种递归思路
举例子,计算一个二叉树的最大深度(leetcode 104),根节点到最远叶子节点的距离。一开始陷入二叉树的细节就不太好写代码了。先思考整棵树和左右子树的关系。
整棵树的最大深度 = max(左子树的最大深度, 右子树的最大深度) + 1要计算子树的最大深度,和计算整个树的深度这个问题是一样的。
原问题:计算整棵树的最大深度
子问题:计算左右子树的最大深度
做循环计算,在使用同一份代码,那么这种相似问题,按道理也应该使用同一份代码计算。但这里的子问题需要把计算结果返回给上一级问题。子问题的规模比原问题小,不断向下(递),但总有尽头,即边界条件,直接返回答案(归)。
为什么这么做是对的?理论依据,数学归纳法证明。
#define MAX(a, b) (((a)>(b)) ? (a) : (b))
int maxDepth(struct TreeNode* root) {
if (root == NULL) return 0;
return MAX(maxDepth(root->left), maxDepth(root->right)) + 1;
}时间复杂度为 O(n),空间复杂度也是 O(n) 。return 怎么知道回到那个节点上去的,函数调用,栈帧。
另外一种思路,递归时除了把节点传下去,还可以把递归的层数传下去,同时维护一个全局变量,当层数大于最大值,就更新全局变量。这个思路在一些题目里也常用到。
二叉树递归练习
二叉树最小深度(leetcode 111)
思路:递归遍历二叉树,同时判断是否为子叶,使用一个全局变量记录最小深度。
路径总和 leetcode 112
关于递归函数参数与返回值的思考
求根节点到叶节点数字之和 leetcode 129
统计二叉树中好节点的数目 leetcode 1448
思路:传入参数中有一个到当前层的最大值,然后维护一个全局变量记录符合要求的节点数。
不使用全局变量?使用 return 返回数量呢?
二叉树的垂序遍历 987
二叉树相同
判断相同二叉树(leetcode 100)
判断相同二叉树(leetcode 100)。根节点相同,然后左子树要相同,右子树也要相同。
如何判断根节点相同?节点的值相同的前提条件是两个节点都不是空节点,因此判空在先。如果两个节点都是空节点,那么返回 true 即相同,一个编程技巧,判断空节点时可以使用 p == q 来判断,只有都为 NULL 才相同,其他的地址是不可能相同的。这也是一个比较巧妙的边界条件。
判断对称二叉树 leetcode 101
如何思考?如果在没有上一题的的前提下,是否能想到这一步
判断平衡二叉树
二叉树的右视图 leetcode 199
验证二叉搜索树
二叉树的遍历。前中后序遍历。
二叉树是不是二叉搜索树:对于一个节点来说,左子树节点值小于,右子树节点值大于。左子树右子树也必须是二叉搜索树。
方法一:前序遍历
区间分割。根据当前的节点值确定区间,然后递归左右子树。
先访问节点值,再递归左右子树的做法就是前序遍历(中左右)
在 dfs 函数中,return 后面的表达,隐含了先访问根节点,然后遍历左子树,遍历右子树。
时间复杂度为 O(n), 空间复杂度为 O(n)。
方法二:中序遍历
按照递归左子树,访问节点值,递归右子树这个顺序遍历,这就是中序遍历(左中右)。
二叉搜索树中序遍历的优秀性质:中序遍历访问节点值是严格递增的。
存在的问题:leetcode OJ 可能会在同一个进程里重复调用 isValidBST 函数,但是 pre 变量还没更新。同时使用 3 个测试用例,都只包含一个节点为0,但是第一个用例通过了,后面两个没过。
这个问题在一些题目里也遇到过,全局变量初始化后,运行测试用例会出问题,但是在核心代码里重新初始化就可以了。可以反向推断出 leetcode 的 OJ 是子啊一个进程里重复调用算法函数的。
可以通过 OJ 的实现
方法三
前序遍历的思路是把区间向下传递,还有一个思路是把节点的范围往上传。
最近公共祖先
层序遍历
广度优先搜索。递归从根节点出发一直往下走,层序遍历则是一行行遍历。
如何从根节点出发得到每层的值?
初始化一个 current 数组,把根节点放进去,然后开始循环。
还需要一个 next 数组,遍历 current,把左右儿子都记录到 next 中。遍历 current 的同时,记录节点值,遍历结束后添加答案。
使用两个数组实现。
两个数组可以合并为一个数组,下一层的节点可以跟在当前层节点后面,这就是队列。
此外还有一题为二叉树的锯齿形层序遍历,和这个题差不多。切入的角度:在保存遍历结果时,反转数组。
类似的 leetcode 513 ,找树左下角的值,思路:返回层序遍历最后一层的第一个元素即可。
二叉树遍历节点
前序遍历的定义就是用递归定义的,二叉树本身也是用递归定义的。关于前中后,指的是中间节点的位置。
后序遍历。
最后更新于
这有帮助吗?