首页 > 试题广场 >

通过先序和中序数组生成后序数组

[编程题]通过先序和中序数组生成后序数组
  • 热度指数:2792 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
给出一棵二叉树的先序和中序数组,通过这两个数组直接生成正确的后序数组。

输入描述:
第一行一个整数 n,表示二叉树的大小。

第二行 n 个整数 a_i,表示二叉树的先序遍历数组。

第三行 n 个整数 b_i,表示二叉树的中序遍历数组。


输出描述:
输出一行 n 个整数表示二叉树的后序遍历数组。
示例1

输入

3
1 2 3
2 1 3 

输出

2 3 1 

备注:

数据保证合法
import java.util.*;
 
public class Main {
    int index = 0;
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int[] pre = new int[n];
        int[] in = new int[n];
        int[] end = new int[n];
        //map存储中序遍历中各结点对应的索引
        Map<Integer,Integer> map = new HashMap<>();
        for(int i=0; i<n; i++)
            pre[i] = scanner.nextInt();
        for(int i=0; i<n; i++){
            in[i] = scanner.nextInt();
            map.put(in[i], i);
        }
        //先将根结点放到最末尾,因为递归遍历左右子树完成后会把根节点返回
        //故在此先将根节点放到正确位置
        end[n-1] = pre[0];
        //递归遍历左右子树
        new Main().endOrder(pre, 0, n-1, in, 0, n-1, end, map);
        //打印后序遍历结果
        for(int x : end)
            System.out.print(x+" ");
    }
    public int endOrder(int[] pre, int preStart, int preEnd, 
                        int[] in, int inStart, int inEnd,
                        int[] end, Map<Integer,Integer> map){
        if(preStart > preEnd)
            return 0;
        //节点只有1个直接返回
        if(preStart == preEnd)
            return pre[preStart];
        //获取前序遍历开始点在中序遍历中的索引
        int k = map.get(pre[preStart]);
        //左子树长度
        int length = k - inStart;
        //递归遍历左子树
        int left = endOrder(pre, preStart+1, preStart+length, in, inStart, k-1, end, map);
        //left不为空即左子树不为空
        if(left != 0)
            end[index++] = left;
        //递归遍历右子树
        int right = endOrder(pre, preStart+length+1, preEnd, in, k+1, inEnd, end, map);
        //right不为空即右子树不为空
        if(right != 0)
            end[index++] = right;
        //遍历结束左右子树后返回根节点
        return pre[preStart];
    }
}

发表于 2022-04-09 11:49:17 回复(0)
先重构二叉树,然后进行后续遍历
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.Stack;

class TreeNode {
    public int val;
    public TreeNode left;
    public TreeNode right;
    public TreeNode(int val) {
        this.val = val;
    }
}

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        String[] params = br.readLine().split(" ");
        int[] preOrder = new int[n];
        for(int i = 0; i < n; i++) preOrder[i] = Integer.parseInt(params[i]);
        params = br.readLine().split(" ");
        int[] inOrder = new int[n];
        for(int i = 0; i < n; i++) inOrder[i] = Integer.parseInt(params[i]);
        // 重建二叉树
        TreeNode root = buildTree(preOrder, inOrder);
        // 后续遍历
        Stack<TreeNode> stack1 = new Stack<>();
        Stack<TreeNode> stack2 = new Stack<>();
        stack1.push(root);
        while(!stack1.isEmpty()){
            TreeNode node = stack1.pop();
            stack2.push(node);
            if(node.left != null) stack1.push(node.left);
            if(node.right != null) stack1.push(node.right);
        }
        while(!stack2.isEmpty()) System.out.print(stack2.pop().val + " ");
    }
    
    private static TreeNode buildTree(int[] preOrder, int[] inOrder) {
        if(preOrder.length != inOrder.length || preOrder.length == 0) return null;
        if(preOrder.length == 1){
            return new TreeNode(preOrder[0]);
        }else{
            int rootVal = preOrder[0];
            TreeNode root = new TreeNode(rootVal);
            int idx = indexOf(inOrder, rootVal);
            root.left = buildTree(Arrays.copyOfRange(preOrder, 1, 1 + idx), Arrays.copyOfRange(inOrder, 0, idx));
            root.right = buildTree(Arrays.copyOfRange(preOrder, 1 + idx, preOrder.length), Arrays.copyOfRange(inOrder, idx + 1, inOrder.length));
            return root;
        }
    }
    
    private static int indexOf(int[] arr, int target) {
        int idx = -1;
        for(int i = 0; i < arr.length; i++){
            if(arr[i] == target){
                idx = i;
                break;
            }
        }
        return idx;
    }
}

发表于 2021-11-16 10:56:03 回复(0)
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] pre = new int[n];
        int[] in = new int[n];
        for (int i = 0; i < n; i++) {
            pre[i] = sc.nextInt();
        }
        for (int j = 0; j < n; j++) {
            in[j] = sc.nextInt();
        }
        
        int[] res = findPos(pre, in);
        for(int i = 0; i < res.length; i++) {
            System.out.print(res[i] + " ");
        }
    }
    
    //无需一定生成二叉树,只分析数组亦可
    //根据当前的先序和中序数组,设置pos arr中最右边空白位置的数,然后划分
    //出左子树的先序、中序数组,以及右子树的先中序数组。
    //先根据右子树的划分设置好后序数组,再根据左子树的划分,从右往左一次设置pos arr。
    public static int[] findPos(int[] pre, int[] in) {
        if (pre == null || in == null)
            return null;
        int len = pre.length;
        int[] pos = new int[len];
        process(pre, in, 0, len-1, 0, len-1, pos, len-1);
        return pos;
    }
    
    public static int process (int[] pre, int[] in, int preS, 
                                int preE, int inS, int inE, 
                                int[] pos, int index) {
        if (preS > preE)
            return index;
        pos[index--] = pre[preS];
        int mid;
        for(mid = inS; in[mid] != pre[preS]; mid++);
        index = process(pre, in, preS+mid-inS+1, preE, mid+1, inE, pos, index);
        return process(pre, in, preS+1, preS+mid-inS, inS, mid-1, pos, index);
    }
}
发表于 2021-06-21 21:43:33 回复(0)
import java.util.*;

public class Main {
	static int[] preArr;
	static int[] inArr;
	static int[] arr;
	static Map<Integer, Integer> map;
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		int n = scanner.nextInt();
        preArr = new int[n];
        inArr = new int[n];
        for(int i=0;i<n;i++){
        	preArr[i] = scanner.nextInt();
        }
         map = new HashMap<Integer, Integer>();
        for(int i=0;i<n;i++){
        	inArr[i] = scanner.nextInt();
        	map.put(inArr[i], i);
        }
        arr = new int[n];
        setArr(0, n-1, 0, n-1, n-1);
        for(int i=0;i<n;i++) {
        	System.out.print(arr[i]+" ");
        }
	}
	
	static  int setArr(int preStart,int preEnd,int inStart,int inEnd,int postIndex) {
		if(preStart>preEnd) return postIndex;
		
		arr[postIndex--] = preArr[preStart];
		int index = map.get(preArr[preStart]);
		
		postIndex = setArr(index - inStart + preStart +1 , preEnd, index+1,inEnd,postIndex);
		return setArr(preStart+1,index - inStart + preStart ,inStart,index-1 ,postIndex);
	}

}

发表于 2019-10-29 15:13:32 回复(0)
之前有道题是根据前中序数组构建二叉树,只要稍微改进一下代码,就可以完成后序序列的输出。
import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        sc.nextLine();
        int[] pre=new int[n];
        int[] me=new int[n];
        for(int i=0;i<n;i++){
            pre[i]=sc.nextInt();
        }
        sc.nextLine();
        for(int i=0;i<n;i++){
            me[i]=sc.nextInt();
        }
        System.out.print(get(pre,me,0,n-1,0,n-1));
    }
     public static int  get(int[] pre,int[] me,int ps,int pe,int ms,int mend){
        if(ps>pe)
            return 0;
        if(ps==pe)//叶子结点
            return pre[ps];
        int index=0;
        for(;index<pre.length;index++){
            if(me[index]==pre[ps])
                break;
        }
        int length=index-ms;
        int left=get(pre,me,ps+1,ps+length,ms,index-1);//左儿子结点
         if(left!=0)
        System.out.print(left+" ");
        int right=get(pre,me,ps+length+1,pe,index+1,mend);//右儿子结点
        if(right!=0)
         System.out.print(right+" ");
      
        return pre[ps];
    }
}
发表于 2019-09-06 16:56:38 回复(0)

问题信息

上传者:小小
难度:
5条回答 6704浏览

热门推荐

通过挑战的用户

查看代码