(拼多多筆試演算法)根據二叉樹的前序遍歷和中序遍歷確定後序遍歷的兩種思路
阿新 • • 發佈:2018-10-31
根據二叉樹的前序遍歷和中序遍歷確定後序遍歷
輸入:第一行:結點數目
第二行:前序遍歷陣列
第三行:中序遍歷陣列
輸出 :後序遍歷陣列
例如:第一行:7
第二行:6 4 2 5 3 1 7
第三行:4 2 5 6 1 3 7
輸出 :5 2 4 1 7 3 6
我思考出來兩種方法
1、根據二叉樹的前序遍歷和中序遍歷還原二叉樹,然後進行後序遍歷
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
public class Main {
static List<Integer> list=new ArrayList<>();
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
int n=scanner.nextInt();
int pre[]=new int[n];
int order[]=new int[n];
int post[]=new int[n];
for (int i = 0; i < pre.length; i++) {
pre[i]=scanner.nextInt();
}
for (int i = 0; i < order.length; i++) {
order[i]=scanner.nextInt();
}
scanner.close();
TreeNode node=reConstructBinaryTree(pre, order);
postOrder(node);
for (int i = 0; i < list.size(); i++) {
post[i]=list.get(i);
}
for (int i = 0; i < post.length; i++) {
System.out.print(post[i]);
if(i!=post.length-1) System.out.print(" ");
}
}
//劍指offer提供思路
public static TreeNode reConstructBinaryTree(int [] pre,int [] in) {
if(pre.length == 0||in.length == 0){
return null;
}
TreeNode node = new TreeNode(pre[0]);
for(int i = 0; i < in.length; i++){
if(pre[0] == in[i]){
node.left = reConstructBinaryTree(Arrays.copyOfRange(pre, 1, i+1), Arrays.copyOfRange(in, 0, i));
node.right = reConstructBinaryTree(Arrays.copyOfRange(pre, i+1, pre.length), Arrays.copyOfRange(in, i+1,in.length));
}
}
return node;
}
//後序遍歷
public static void postOrder(TreeNode node ) {
if(node!=null) {
postOrder(node.left);
postOrder(node.right);
list.add(node.val);
}
}
// 6 4 2 5 3 1 7
// 4 2 5 6 1 3 7
}
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
缺點:時間複雜度太高(重建二叉樹遞迴,後序遍歷遞迴)
空間複雜度太高(二叉樹 ,List )
2、根據二叉樹的遍歷特點進行求解
前序遍歷:左根右 6 4 2 5 3 1 7
中序遍歷:左根右 4 2 5 6 1 3 7
後序遍歷:左右根 5 2 4 1 7 3 6
**由此可以看出,前序遍歷的第一個節點,是後序遍歷的最後一個節點
前序遍歷的第一個節點,在中序遍歷中將樹一分為2,
即根節點 6,左子樹 4 2 5,右子樹 1 3 7,繼續向下遞迴即可**
//坑爹啊,調程式除錯到現在,遞迴程式太難除錯
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scanner=new Scanner(System.in);
int n=scanner.nextInt();
int pre[]=new int[n];
int order[]=new int[n];
int post[]=new int[n];
for (int i = 0; i < pre.length; i++) {
pre[i]=scanner.nextInt();
}
for (int i = 0; i < order.length; i++) {
order[i]=scanner.nextInt();
}
coverTree(pre,order,post,post.length-1);
for (int i = 0; i < post.length; i++) {
System.out.print(+post[i]);
if(i!=post.length-1)System.out.print(" ");
}
}
private static void coverTree(int[] pre, int[] order, int[] post, int i) {
for (int j = 0; j < order.length; j++) {
if(order[j]==pre[0]) {
//賦值
post[i]=order[j];
//前面
coverTree(Arrays.copyOfRange(pre, 1, j+1), Arrays.copyOfRange(order, 0, j),post,i-j-1);
//筆試的時候這塊一直有問題,調了一個小時才調出來,多除錯遞迴程式啊 ,血琳琳的教訓
/*
之前 前面寫的是是
coverTree(Arrays.copyOfRange(pre, 1, j+1), Arrays.copyOfRange(order, 0, j),post,j-1);因為j一直在變啊,沒體會出來,需要改成i-j-1
*/
//後面
coverTree(Arrays.copyOfRange(pre, j+1, pre.length), Arrays.copyOfRange(order, j+1,order.length),post,i-1);
}
}
}
// 6 4 2 5 3 1 7
// 4 2 5 6 1 3 7
}
多思考思考第二種方法 還是可以想出來的~~~