617.合并二叉树
题目要求 按位置 合并两个二叉树。
分析:这个题目如果用层序遍历,那么需要用一个值去代替每一个空值,也就是位置不好定,做起来肯定麻烦!因此,优先用递归的前序遍历!遍历的方法按照递归3部曲进行即可。
本题对于递归思想进行一下总结和理解:
- 因为树是一种递归结构,你可以理。解为:树是由一颗颗树构成的!构成树 的树称为子树。因此,在我们合并两个子树的过程中,我们的思路应该是这样的:
- 首先合并两颗树的两个根节点
- 其次合并两颗树的两个左节点(而合并两个左节点的过程,其实就是合并两个左子树的两个根节点的过程,因此就是将两个左子树进行合并,合并函数就是过程1中的函数)。
- 然后合并两颗树的两个右节点(而合并两个右节点的过程,其实就是合并两个 右子树的两个根节点 的过程,因此就是将两个右子树进行合并,合并函数就是过程1中的函数)。
- 因此,就形成了一种递归思想,即:处理树的子树/子节点(左子树/右子树、左节点/右节点)的过程其实是和处理 树/根节点的过程、函数(方法)是一样一样的!
- 最后根据上述的思想去考虑递归函数所需要传入的参数、返回值等,就清晰得多啦!
700.二叉搜索树中的搜索
二叉搜索树是一个有序树:
- 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
- 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
- 它的左、右子树也分别为二叉搜索树
本题可以用递归法进行遍历,方法按照递归3部曲,不难!
想重点记录的是如何用迭代法对二叉树进行搜索,
对于二叉搜索树可就不一样了,因为二叉搜索树的特殊性,也就是节点的有序性,可以不使用辅助栈或者队列就可以写出迭代法。
对于一般二叉树,递归过程中还有回溯的过程,例如走一个左方向的分支走到头了,那么要调头,在走右分支。
而对于二叉搜索树,不需要回溯的过程,因为节点的有序性就帮我们确定了搜索的方向。
class Solution {
public:
TreeNode* searchBST(TreeNode* root, int val) {
while (root != NULL) {
if (root->val > val) root = root->left;
else if (root->val < val) root = root->right;
else return root;
}
return NULL;
}
};
98.验证二叉搜索树
要知道中序遍历下,输出的二叉搜索树节点的数值是有序序列。
有了这个特性,验证二叉搜索树,就相当于变成了判断一个序列是不是递增的了。
可以把二叉树转变为数组来判断,是最直观的!
这道题目比较容易陷入两个陷阱:
- 陷阱1
不能单纯的比较左节点小于中间节点,右节点大于中间节点就完事了。
写出了类似这样的代码:
if (root->val > root->left->val && root->val < root->right->val) {
return true;
} else {
return false;
}
我们要比较的是 左子树的 所有节点小于中间节点,右子树所有节点大于中间节点。所以以上代码的判断逻辑是错误的。
后面就是正常的递归3部曲:
注意递归函数要有bool类型的返回值, 我们在二叉树:递归函数究竟什么时候需要返回值,什么时候不要返回值? (opens new window)中讲了,只有寻找某一条边(或者一个节点)的时候,递归函数会有bool类型的返回值。
其实本题是同样的道理,我们在寻找一个不符合条件的节点(某一特性),如果没有找到这个节点就遍历了整个树,如果找到不符合的节点了,立刻返回。
总结:验证二叉搜索树这道题用的是双指针的思路!