🚩传送门:牛客题目
力扣题目

题目

给定一棵二叉搜索树和其中的一个节点 [NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图1 ,找到该节点在树中的中序后继。如果节点没有中序后继,请返回 [NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图2

节点 [NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图3 的后继是中序遍历的顺序节点 [NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图4 的下一个节点。

示例 1:
[NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图5

输入:root = [2,1,3], p = 1 输出:2 解释:这里 1 的中序后继是 2。请注意 p 和返回值都应是 TreeNode 类型。

示例 2:
[NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图6

输入:root = [5,3,6,2,4,null,null,1], p = 6 输出:null 解释:因为给出的节点没有中序后继,所以答案就返回 null 了。

解题思路:牛客

牛客题目中,树中的结点不仅包含左右子结点,同时包含指向父结点的next指针,函数的形参只给出节点 [NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图7 ,而没有根结点 [NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图8
image.png
因此对于 [NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图10 我们只需要考虑以下两种情况:

  1. 节点 [NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图11 有右孩子即 [NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图12
  2. 节点 [NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图13 无右孩子即 [NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图14

节点 [NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图15 有右孩子情形:
image.png
节点 [NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图17 无右孩子情形:

需要考虑 [NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图18 是父亲 [NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图19 的左子树还是右子树

  • [NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图20 是父亲 [NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图21的左子树,父亲 [NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图22就是自己的下一个序列
  • [NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图23 是父亲 [NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图24的右子树,父亲 [NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图25就是自己的上一个序列,此时[NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图26继续上述检查,直至 [NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图27

image.png

我的代码

  1. public class Solution {
  2. public TreeLinkNode GetNext(TreeLinkNode pNode) {
  3. // 如果有右子树,下一个序列一定在右子树
  4. // 在右子树中查找最小值
  5. if (pNode.right != null) {
  6. pNode = pNode.right;
  7. // 最小值一定是最左结点
  8. while (pNode.left != null) {
  9. pNode = pNode.left;
  10. }
  11. return pNode;
  12. }
  13. // 右子树是空的,判断自己是父亲的左子树还是右子树
  14. // 自己是父亲的左子树,父亲就是自己的下一个序列
  15. // 自己是父亲的右子树,父亲就是自己的上一个序列,此时需要继续向上寻找,直至pNode.next == null
  16. while (pNode.next != null) {
  17. // pNode是父亲的左子树,父亲就是自己的下一个序列
  18. if (pNode.next.left == pNode)
  19. return pNode.next;
  20. pNode = pNode.next;
  21. }
  22. return null;
  23. }
  24. }

解题思路:力扣

力扣题目中,树中的结点仅包含左右子结点,函数的形参不光给出节点 [NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图29 ,还给出根结点 [NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图30
image.png
我们知道中序遍历的规则:是由小到大有序的,比[NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图32大的值一定后遍历

我们只要从根节点二叉树搜索一定能找到第一个大于 [NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图33的结点 [NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图34,结点[NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图35一定是[NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图36的后面遍历结点,但具体是不是后继不知道

那么[NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图37 ,即当前[NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图38被标记为是[NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图39后遍历的结点,只需 [NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图40[NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图41的左子树看看,因为比 [NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图42先遍历的定在 [NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图43的左子树。

  • 如果左子树中出现了 [NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图44则说明此时[NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图45[NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图46后遍历的结点,且比[NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图47标记的早,因此刷新 [NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图48
  • 如果左子树中 [NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图49则去 [NC]279. 二叉树的下一个结点/二叉搜索树中的中序后继 - 图50的右子树看看

    1. class Solution {
    2. public TreeNode inorderSuccessor(TreeNode pRoot, TreeNode pNode) {
    3. TreeNode cur = pRoot;
    4. TreeNode result = null;
    5. while (cur!=null) {
    6. if (cur.val > pNode.val) {
    7. result = cur;
    8. cur = cur.left;
    9. } else {
    10. cur = cur.right;
    11. }
    12. }
    13. return result;
    14. }
    15. }