首先解题思路来自b站某高手,思路清奇,请看官先看视频:
老铁们,看完视频是否有茅塞顿开的感觉 XD
这个方法强悍之处就在,y轴可以用前序,后序(倒过来写),层序。一行代码都不用改的情况下,可以解三种题(已知前、中序求后序;已知中、后序求前序;已知层、中序求前或后序)!
代码见下,主要是buildTreeNode()方法,完美还原了视频的解题思路,老铁们悟了记得点个赞,谢啦。
import java.util.*;
public class Demo二叉树 {
/**二叉树类
*data 根节点
*left 左子树
*right 右子树
*/
static class TreeNode {
public String data;
public TreeNode left;
public TreeNode right;
public TreeNode(String data) {
super();
this.data = data;
}
}
/**
* 二叉树,根据前序遍历和中序遍历求后序遍历
* @param args
*/
public static void main(String[] args) {
String qian = "ABCDEFGHIJ";// 前序
String zhong = "CBAFEDIHJG";// 中序
TreeNode treeNode = new TreeNode(qian.substring(0, 1));//根节点
buildTreeNode(qian, zhong, treeNode, null, null);//补全treeNode的子树
List<String> resultList = new ArrayList<String>();
houxu(treeNode, resultList);//解析treeNode结构,按后序遍历出来
System.out.println(resultList.toString());//[C, B, F, E, I, J, H, G, D, A]
}
/**
* 构建二叉树结构
* @param qian 前序字符串 或 后序字符串倒写 或 层序字符串 (兼容3种顺序)
* @param zhong 中序字符串
* @param tn 二叉树(上层递归的子树)
* @param leftLimit 中序字符串取值范围,左边界
* @param rightLimit 中序字符串取值范围,右边界
*/
public static void buildTreeNode(String qian, String zhong, TreeNode tn, Integer leftLimit, Integer rightLimit) {
int indexQian = qian.indexOf(tn.data);//tn的根节点在前序中的位置
int indexZhong = zhong.indexOf(tn.data);//tn的根节点在中序中的位置
for (int i = indexQian + 1; i < qian.length(); i++) {//在前序字符串中由前往后找tn的子树
String iString = String.valueOf(qian.charAt(i));//当前要找的根节点字符
int j = zhong.indexOf(iString);//在中序字符串中的位置
//如果左子树没赋值,且 中序字符串中该字符在tn的根节点左边,且 在左边界的右边,则 找到左子树(的根节点)。
if (tn.left == null && j < indexZhong && ((leftLimit != null && j > leftLimit) || leftLimit == null)) {
tn.left = new TreeNode(iString);
buildTreeNode(qian, zhong, tn.left, leftLimit, indexZhong);//递归时更新右边界,因为中序字符串中,一个二叉树的左子树的所有子树都在这个二叉树的左边。
//如果右子树没赋值,且 中序字符串中该字符在tn的根节点右边,且 在右边界的左边,则 找到右子树(的根节点)。
} else if (tn.right == null && j > indexZhong && ((rightLimit != null && j < rightLimit) || rightLimit == null)) {
tn.right = new TreeNode(iString);
buildTreeNode(qian, zhong, tn.right, indexZhong, rightLimit);//递归时更新左边界,道理和上面同理。
}
if (tn.left != null && tn.right != null) {
break;//tn的左右子树都找到了就break,找不到也没关系,for循环完后正常结束。
}
}
}
// 前序遍历
public static void qianxu(TreeNode tn, List<String> list) {
if (tn == null) {
return;
}
list.add(tn.data);
qianxu(tn.left, list);
qianxu(tn.right, list);
}
// 中序遍历
public static void zhongxu(TreeNode tn, List<String> list) {
if (tn == null) {
return;
}
zhongxu(tn.left, list);
list.add(tn.data);
zhongxu(tn.right, list);
}
// 后序遍历
public static void houxu(TreeNode tn, List<String> list) {
if (tn == null) {
return;
}
houxu(tn.left, list);
houxu(tn.right, list);
list.add(tn.data);
}
// 层序遍历
public static void cengxu(List<TreeNode> treeNodes, List<String> list) {
if (treeNodes.size() == 0) {
return;
}
ArrayList<TreeNode> tns = new ArrayList<TreeNode>();
for (TreeNode tn : treeNodes) {
list.add(tn.data);
if (tn.left != null) {
tns.add(tn.left);
}
if (tn.right != null) {
tns.add(tn.right);
}
}
cengxu(tns, list);
}
}