在前文 二叉树的遍历 中,讨论了二叉树的三种遍历方式的递归和非递归实现,以及层次遍历的实现。本文在此基础之上,来讨论面试题中,关于求二叉树节点类的面试题。此类题目,有二叉树的遍历算法改造而求解。
全文结构如下:
![fefdeb0c258c860a174f1cfe5714799f.png](https://i-blog.csdnimg.cn/blog_migrate/db42898b7ddc4dc5dc6770d24582abd0.png)
对应的oj练习地址如下:
1.二叉树的节点个数 - leetcode222
2.二叉树的下一个结点_牛客网
3.二叉搜索树的最近公共祖先-Leetcode235
4.二叉树的最近公共祖先-leetcode236
5.二叉搜索树中第K小的元素-leetcode230
1.二叉树中节点的个数
递归解法:
1
递归代码如下:
class
非递归解法:
1
基于中序遍历的非递归解法代码如下
class
两者运行效果对比如下:
![a1b562e8a9179fd34a22bf79dd6d076a.png](https://i-blog.csdnimg.cn/blog_migrate/a1bac9eab94df0061e08ae4eb221f7e4.png)
![77b4bfc9f5e6216bc1116b61b6ccb6ed.png](https://i-blog.csdnimg.cn/blog_migrate/c7c68525bd404f280f8265daaa0181ae.png)
从上面的对比过程中,可以看到递归版的代码简洁,而且运行效率也快。在做算法题时,优先考虑递归方法来解决二叉树的问题。
2.二叉树中序遍历的下一个节点
题目描述:
给定一个二叉树和其中的一个结点
解题思路:
1)遍历二叉树到指定的节点。
2)分情况讨论:
- 若当前节点有右子树,则下一个节点为其右子树的最左叶子节点。
- 若当前节点没有右子树,则沿着父节点指针向上回溯,找到满足下面条件的节点。
若存在一个节点满足,该节点的左孩子是当前节点的祖先节点。则后续节点为该节点。
若回溯到根节点后,仍然未找到,无后继节点。
代码如下:
public
3.二叉搜索树的最近公共祖先
思路:
在二叉搜索树中,左子树中叶子节点的值小于根节点;右子树中叶子节点的值大于根节点。
对于查找节点p,q的最近公共祖先,可按照如下步骤:
1) 若p,q分别在左右子树中,则root节点为最近公共祖先。
2)若p,q都在左子树中,则以左孩子为根节点,继续(1)操作。
3)若p,q都在右子树中,则以右孩子为根节点,继续(1)操作。
递归版实现如下:
class
非递归版思路:
思路:我们只需要找到分割点就可以了。
这个分割点就是能让节点 p和节点q能在同一颗子树上的那个节点,
或者分割点是节点p和节点q中的一个,这种情况下其中一个节点是另一个节点的父亲节点。
非递归版代码实现:
class
4.求二叉树中两个节点的最低公共祖先节点
![8d9ae4145f14ca174d3f6d1811ef5a9d.png](https://i-blog.csdnimg.cn/blog_migrate/029b1f1cada1fbb3aa9e5d746e9631ef.png)
前提条件:
1)所有节点的值都是唯一的。
2)p、q 为不同节点且均存在于给定的二叉树中。
递归解法思路:
1、在左、右子树中分别查找是否包含p或q。
如果p,q分别在左右子树两侧,即:左子树包含p,右子树包含q 或者左子树包含q,右子树包含p
则lowestCommonAncestor,返回的是出现某一个节点的位置。
若有,则返回该节点,若没有,则返回null.那么此时的根节点就是最近公共祖先。
2、如果左子树包含p和q,那么到root->left中查找,最近公共祖先在左子树里面
3、如果右子树包含p和q,那么到root->right中查找,最近公共祖先在右子树里面
4、注意:不可能left和right的返回值同时都是null。因为p,q肯定在二叉树中。
递归代码如下:
class
5.二叉搜索树中第K小的元素
思路:
中序遍历二叉搜索树,可以得到一个升序的序列。
非递归版代码:
public