对于重建二叉树的场景,通常是有中序遍历的,不然无法知道根节点在哪。因为前序遍历是根节点在最前面,后序遍历是根节点在最后面,所以无法明确的区分出来哪些点是左子树的点,哪些点是右子树的点。
对于重建二叉树来说,这里我们选择以前序遍历和中序遍历为例进行说明。
比如前序遍历为:
A B D E C F
比如中序遍历为:
D B E A C F
那么我们有如下的思维步骤:
(1).根据前序遍历,我们知道A是根节点。
(2).根据中序遍历,我们知道 D B E为左子树,我们知道 C F为右子树。
(3).这样第一个根节点就找到了,然后我们再来找左子树的根节点。
(4).根据前序遍历,我们可以发现B点是左子树的根节点。
(5).根据中序遍历,我们可以发现D是左子树的左子树,E是左子树的右子树。
那么我们如何来把上面的思维方式变成代码呢?
我们这里给出一个具体的代码范例吧:
package com.mengzhidu.teach.algorithm.tree.demo.reduce;
import com.mengzhidu.teach.algorithm.tree.demo.TreeNode;
import java.util.ArrayList;
/**
* 根据前序遍历和中序遍历来重建二叉树
* 这里使用了递归的方式,主要的思路是基于如下几点:
* 1.根据前序遍历首先确定根节点
* 2.根据中序遍历确定左子树和右子树的长度
* 3.找到前序遍历的左子树和右子树
* 4.使用递归的方式来创建其左右子树
*/
public class ReduceByPreAndInDemo {
public static void main(String[] args) {
ArrayList<String> preOrderList = new ArrayList<>();
preOrderList.add("A");
preOrderList.add("B");
preOrderList.add("D");
preOrderList.add("E");
preOrderList.add("C");
preOrderList.add("F");
ArrayList<String> inOrderList = new ArrayList<>();
inOrderList.add("D");
inOrderList.add("B");
inOrderList.add("E");
inOrderList.add("A");
inOrderList.add("C");
inOrderList.add("F");
TreeNode root = reduceByPreAndIn(preOrderList, inOrderList, 0, preOrderList.size()-1, 0, inOrderList.size()-1);
System.out.println("前序遍历");
preOrder(root);
System.out.println("中序遍历");
inOrder(root);
}
private static TreeNode reduceByPreAndIn(ArrayList<String> preOrder, ArrayList<String> inOrder,
int preCurrent, int preEnd, int inCurrent, int inEnd) {
if (preCurrent > preEnd || inCurrent > inEnd) {
return null;
}
String value = preOrder.get(preCurrent);
TreeNode current = new TreeNode(value, null, null);
int span = -1;
for (int i = inCurrent; i <= inEnd; i++) {
if (inOrder.get(i).equals(value)) {
span = i;
break;
}
}
if (span == -1) {
return null;
}
// 前序遍历中的分界线
int fix = preEnd - inEnd + span;
current.setLeft(reduceByPreAndIn(preOrder, inOrder, preCurrent +1, fix, inCurrent, span -1));
current.setRight(reduceByPreAndIn(preOrder, inOrder, fix + 1 , preEnd, span + 1 , inEnd));
return current;
}
private static void preOrder(TreeNode root) {
if (root == null) {
return;
}
System.out.println(root.getValue());
preOrder(root.getLeft());
preOrder(root.getRight());
}
private static void inOrder(TreeNode root) {
if (root == null) {
return;
}
inOrder(root.getLeft());
System.out.println(root.getValue());
inOrder(root.getRight());
}
}
其实这里主要是分清楚哪些变量是根据哪些变量得来的即可,对于是否需要加1减1这些地方的值,我们自己列一个具体的情况分析一下即可。