LeetCode No.105 Construct Binary Tree from Preorder and Inorder Traversal

题目:


意思就是说,通过前序遍历序列和中序遍历序列还原出二叉树。

思路:

主要思路有递归和非递归两种思路,其中递归思路比较直观也容易理解。在这里只讲非递归的。

代码:

class Solution:
    def buildTree(self, preorder, inorder):
        if len(preorder) == 0:
            return None
        else:
            result = TreeNode(preorder[0])
            root = result
            nodeStack = [root]
            i = 0
            p = 0
            while p < len(preorder):
                #找最左节点
                if preorder[p] != inorder[i]:
                    root.left = TreeNode(preorder[p+1])
                    root = root.left
                    nodeStack.append(root)
                else:
                    #找到了最左节点
                    while  len(nodeStack) and nodeStack[-1].val == inorder[i]:
                        i += 1
                        root = nodeStack.pop()
                    if p+1 <len(preorder):
                        root.right = TreeNode(preorder[p+1])
                        root = root.right
                        nodeStack.append(root)
                p += 1
            return result

结果:

讲解:

以这个二叉树为例,preorder=[1,2,4,8,5,3,6,9,10,7],inorder=[4,8,2,5,1,9,6,10,3,7]。

显然可以看到,4是整棵树的最左边的节点,也是inorder序列的第一个数字,而从preorder序列要经过1、2之后才遍历到4。根据前序序列本身的性质,从子树的根节点遍历到最左节点,preorder[p+1]均为preorder[p]的左子树。把这些遍历过的节点压栈。

怎么判断已经遍历到最左节点了呢?显然,inorder[0]即是整棵树的最左节点。此时需要考虑我们遍历过的节点是否存在右子树。根据序列的性质,已知preorder[p+1]是preorder[p]的左节点,以2和4为例,那么在中序序列中,在遍历4之后,遍历4的右节点,再遍历4的父节点2,所以4和2之间的序列就是4的右子树的序列。

所以,找到最左节点之后的while循环,相当于从下到上,寻找存在右子树的节点,找到之后把右子树的根节点也压栈,进行同样的操作。

后记:这个解法一开始是在discuss里面看到的,不过原版是C++,理解了一下思路再自己打一遍python版本。

猜你喜欢

转载自blog.csdn.net/qq_39178023/article/details/80152417
今日推荐