题目:
意思就是说,通过前序遍历序列和中序遍历序列还原出二叉树。
思路:
主要思路有递归和非递归两种思路,其中递归思路比较直观也容易理解。在这里只讲非递归的。
代码:
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版本。