目录
1、从前序与中序遍历序列构造二叉树 leetcode105
先序遍历的顺序是 root -> left -> right,中序: left -> root -> right,这就能方便的从根开始构造一棵树。
首先,preorder 中的第一个元素一定是树的根,这个根又将 inorder 序列分成了左右两棵子树。现在我们只需要将先序遍历的数组中删除根元素,然后重复上面的过程处理左右两棵子树。先序的遍历结果决定了我们只能先创建左子树再创建右子树,借助 “队列” 数据结构将先序中根节点依次取出。该方法的核心就是用先序序列元素作即根节点分割中序序列。
给定二叉树结构如下:
1
/ \
2 3
/ \ / \
4 5 6 7
动图创建如下:
力扣官方题解:《已知先序和中序构造二叉树》
递归实现如下,注意终止条件:前序和中序序列为空,实际上如果给定序列是有效的,那么终止条件 中序序列一个为空就够了。
public TreeNode buildTree(int[] preorder, int[] inorder) {
if(preorder == null || inorder == null || preorder.length < 1 || inorder.length < 1){
return null;
}
Queue<Integer> preorderQueue = new LinkedList<>();
List<Integer> inorderList = new ArrayList<>();
for(int i = 0; i < preorder.length; i++){
preorderQueue.add(preorder[i]);
inorderList.add(inorder[i]);
}
return buildTree(preorderQueue,inorderList);
}
private TreeNode buildTree(Queue<Integer> preorder, List<Integer> inorder) {
if(preorder.isEmpty()|| inorder.isEmpty()){
return null;
}
int nodeVal = preorder.poll();
TreeNode curNode = new TreeNode(nodeVal);
int index = inorder.indexOf(nodeVal);
if(index < 0){
return null;
}
List<Integer> letf = inorder.subList(0,index);
List<Integer> right = inorder.subList(index + 1,inorder.size());
curNode.left = buildTree(preorder,letf);
curNode.right = buildTree(preorder,right);
return curNode;
}
2、从中序与后序遍历序列构造二叉树 leetcode106
如何根据两种遍历序列构造树:中序,和先序/后序/等等。通常从先序序列或者后序序列开始,根据不同遍历方法的规律,选择合适的节点构造树。
先序序列的 第一个 节点是根节点,然后是它的左孩子,右孩子等等。
后序序列的 最后一个 节点是根节点,然后是它的右孩子,左孩子等等。
从先序/后序序列中找到根节点,根据根节点将中序序列分为左子树和右子树。从中序序列中获得的信息是:如果当前子树为空(返回 None),否则继续构造子树。
后序的遍历结果决定了我们只能先创建右子树再创建左子树(先序+中序差异之处),借助 “栈” 数据结构将后序中根节点依次弹出。该方法的核心就是用后序序列元素即根节点分割中序序列。
代码实现如下:
public TreeNode buildTree(int[] inorder, int[] postorder) {
if(inorder ==null || postorder ==null){
return null;
}
List<Integer> inorderList = new ArrayList<>();
Stack<Integer> postorderStack = new Stack<>();
for(int i=0;i< inorder.length;i++){
inorderList.add(inorder[i]);
postorderStack.push(postorder[i]);
}
return bulidTree(inorderList,postorderStack);
}
private TreeNode bulidTree(List<Integer> inorder,Stack<Integer> postorder){
if(inorder.isEmpty() || postorder.isEmpty()){
return null;
}
int val = postorder.pop();
int index = inorder.indexOf(val);
if(index < 0){
return null;
}
List<Integer> left = inorder.subList(0,index);
List<Integer> right = inorder.subList(index + 1,inorder.size());
TreeNode curNode = new TreeNode(val);
curNode.right= bulidTree(right,postorder);//先创建右子树
curNode.left= bulidTree(left,postorder);
return curNode;
}
3、LeetCode297. 二叉树的序列化与反序列化
4、小结
无论是先序+中序 还是 中序+ 后序 构建唯一二叉树的原理都是用根节点将中序序列分割成左右两个子树。需要说明的是 先序和后序在本质上都是将父节点与子结点进行分离,但并没有指明左子树和右子树的能力,因此得到这两个序列只能明确父子关系,而不能确定一个唯一的二叉树。记住下面这个简单的例子。