算法思想一:暴力法

解题思路:

直接模拟题意。题意需要找到某个结点中序遍历的下一个结点,那很显然可以这样:
1、根据给出的结点求出整棵树的根节点
2、根据根节点递归求出树的中序遍历,存入res中
3、在res中查找当前结点,则当前结点的下一结点即为所求。
1、当找到当前结点是数组最后一个元素,则直接返回 None/Null
2、当找到当前结点不是数组最后一个元素,则返回下一个数组结点
二叉树中序遍历DBHEIAFCG图例:

代码展示:

Python版本
class Solution:
    def GetNext(self, pNode):
        # write code here
        # 中序遍历存储数组
        res = []
        cur = pNode
        while cur.next:
            cur = cur.next
        self.inorder(cur, res)
        
        for i in range(len(res)):
            if pNode == res[i]:
                # 判断 i 是不是最后一个结点,是则返回none,否则返回下一个数组结点
                return None if i == len(res)-1 else res[i+1]
        return None
    # 递归遍历中序
    def inorder(self, cur, res):
        if cur:
            self.inorder(cur.left, res)
            res.append(cur)
            self.inorder(cur.right, res)

复杂度分析:

时间复杂度O(N):N表示树的结点数量,递归遍历整个树结点,查找遍历数组,最差情况都是O(N)
空间复杂度O(N):存储二叉树中序遍历数组res占用空间O(N)

算法思想二:最优解法

解题思路:

仔细观察,可以把中序(DBHEIAFCG)下一结点归为几种类型:
1、有右子树,下一结点是右子树中的最左结点,例如 B,下一结点是 H
2、无右子树,且结点是该结点父结点的左子树,则下一结点是该结点的父结点,例如 H,下一结点是 E
3、无右子树,且结点是该结点父结点的右子树,则一直沿着父结点追朔,直到找到某个结点是其父结点的左子树,如果存在这样的结点,那么这个结点的父结点就是我们要找的下一结点。例如 I,下一结点是 A;例如 G,并没有符合情况的结点,所以 G 没有下一结点

代码展示:

JAVA版本
public class Solution {
    public TreeLinkNode GetNext(TreeLinkNode pNode)
    {
        if(pNode == null) return null;
        
        //如果当前结点的右子树是不为空
        if(pNode.right != null){
            pNode = pNode.right;
            while(pNode.left != null)
                pNode = pNode.left;
            return pNode;
        }
        //当前结点无右子树时,判断结点是父结点的左子树还是右子树
        while(pNode.next != null){
            if(pNode.next.left == pNode)
                return pNode.next;
            pNode = pNode.next;
        }
        return null;
    }
}

复杂度分析:

时间复杂度O(N):N表示树的结点数量,最差情况查找整个二叉树
空间复杂度O1):不需要额外空间