【剑指offer刷题】JZ57:给定二叉树和某个结点,找到中序遍历顺序的下一个结点

转载请注明出处:https://blog.csdn.net/loiter2/article/details/107448160

【剑指offer刷题】JZ57:给定二叉树和某个结点,找到中序遍历顺序的下一个结点

    • 1、题目分析
      • 1.1 暴力解法思路
      • 1.2 类似找规律
    • 2、代码实现
      • 2.1 暴力解法的代码实现
      • 2.2 总结规律方法的代码实现

该文章只是用来记录一下刷题过程中不会的点,但是自己太菜,做不出来的部分,有参考牛客网剑指offer部分的官方解答和各种大神的解答。本文的记录和解答用的Java语言。

1、题目分析

给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。

//二叉树结点,其中next是指父亲结点
public class TreeLinkNode {
     
    int val;
    TreeLinkNode left = null;
    TreeLinkNode right = null;
    TreeLinkNode next = null;

    TreeLinkNode(int val) {
     
        this.val = val;
    }
}

上述代码是题目给出的二叉树结点
很有趣的是,牛客网官方解答,直接提出,这道题作为笔试题和面试题的两种解答方式。

  • 作为笔试题,自然是求思路清晰、解答简单,追求accept,自然可能不是最优解,时间复杂度和空间复杂度可以不是最好的。
  • 作为面试题,面试官自然想听到的就是最优解

因此本文也把两种方式的解答都记录下来

1.1 暴力解法思路

最直接暴力的方法,要求某个结点中序遍历顺序的下一个结点,那直接得到整棵二叉树的中序遍历结果,然后在中序遍历结果中,找到要求的结点的下一个结点即可
具体思路为:

  • 基于给出的结点,不断找父结点,直到找到整棵二叉树的根结点
  • 基于根结点,中序遍历整棵二叉树,将遍历结果存入数组中
  • 从数组中找到需要的目标结点

这种做法的思路还是很明确的,也比较容易想到,时间复杂度也没有特别高,找到父结点为O(n),遍历二叉树为O(n),找到目标节点为O(n),总体为3*O(n);空间复杂度为存储遍历结果O(n)。
时间复杂度:O(n);
空间复杂度:O(n);

1.2 类似找规律

据说面试时,你能给面试官图解解释,面试官会比较高兴。本题没有啥特别的算法套路可以用,因此就自己画个二叉树找找规律呗,分析分析总共有几种情况,分情况给出结果即可。
【剑指offer刷题】JZ57:给定二叉树和某个结点,找到中序遍历顺序的下一个结点_第1张图片
上图给出了一个简单的二叉树,数字即为中序遍历的顺序
下面就分析每一个结点与下一个结点的关系:

  • 1–>2:1没有子结点,下一结点是其父结点,并且1是其父结点的左子结点;
  • 2–>3:2有左右两个子结点,下一结点是其右子结点;
  • 3–>4:3没有子结点,下一结点是父结点的父结点(爷爷结点),并且其父结点是爷爷结点的左子结点;
  • 4–>5:4有左右两个子结点,下一结点是右子树中最左叶子结点;
  • 5–>6:与1–>2是一致的;
  • 6–>7:7是尾结点;

总结一下上述情况:

  1. 一个结点有右子树时,那该节点的下一个结点一定在右子树当中;右子树只有一个结点时,就是该结点本身,像上述2–>3;右子树有多个结点时,就是右子树中最左叶子结点,像上述4–>5.
  2. 上述5–>6与1–>2是一致的,两者与3–>4其实也是类似的。当某个结点A不断往上追溯,发现A本身所在的子树是某个结点B的左子树时,这个结点B就是结点A的下一个结点。结合图例可以比较容易的理解。
  3. 最后一种情况就是,当某个结点A不断往上追溯,都追溯到根节点了,A本身所在的子树仍然是右子树,就是说明A是尾结点,下一个结点为null。

理清上述三种情况后,分情况讨论,即可得出结果。该种方法,只需基于某个结点往上或者往下追溯,不需要存储,因此
时间复杂度:O(n);
空间复杂度:O(1);

2、代码实现

作为学习,最好看了上面的思路后,自己去实现代码,学习效果更好。

2.1 暴力解法的代码实现

public class Solution {
     
    public TreeLinkNode GetNext(TreeLinkNode pNode)
    {
     
        if (pNode == null) return null;
        //往上追溯,找到二叉树根节点
        TreeLinkNode root = pNode;
        while (root.next != null){
     
            root = root.next;
        }
        
        ArrayList<TreeLinkNode> result = new ArrayList();
        //中序遍历,并且把遍历得到的结果放在数组result中
        inorderTraversal(root, result);
        //在数组result中找到pNode结点的后一个结点
        return findNext(pNode, result);
    }
    //递归方法中序遍历,并且把遍历得到的结果放在数组result中
    public void inorderTraversal(TreeLinkNode root,
                                 ArrayList<TreeLinkNode> result){
     
        if (root == null) return;
        
        inorderTraversal(root.left, result);
        result.add(root);
        inorderTraversal(root.right, result);
        //return result;
    }
    //在数组result中找到thisNode结点的后一个结点,并返回
    public TreeLinkNode findNext(TreeLinkNode thisNode,
                                 ArrayList<TreeLinkNode> result){
     
        Iterator<TreeLinkNode> it = result.iterator();
        while (it.hasNext()){
     //首先找到thisNode
            if (it.next().equals(thisNode)){
     
                break;
            }
        }
        if (it.hasNext()){
     
            return it.next();
        }else {
     
            return null;
        }
    }
}

2.2 总结规律方法的代码实现

public class Solution {
     
    public TreeLinkNode GetNext(TreeLinkNode pNode){
     
        if (pNode == null) return null;
        //第一种情况,有右子树,则下一个结点一定在右子树中
        //右子树只有一个结点,则是其本身
        //右子树有多个结点,则是右子树的最左叶子结点
        if (pNode.right != null){
     
            TreeLinkNode rightTree = pNode.right;
            while (rightTree.left != null) {
     
                rightTree = rightTree.left;
            }
            return rightTree;
        }
       	//第二种情况,没有右子树,则往上追溯,找到自身所在子树是某个结点左子树的结点
        while (pNode.next != null){
     
            TreeLinkNode father = pNode.next;
            if (father.left == pNode){
     
                return father;
            }
            pNode = pNode.next;
        }
        //第三种情况,尾结点
        return null;
    }
}

你可能感兴趣的:(剑指offer刷题,二叉树,算法,数据结构,java)