【剑指offer】【java】【树】重建二叉树

题目

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

思路

1.树 用递归实现
2.前序遍历的第一个是根节点,然后根据这个根节点找到中序遍历中的根节点 同时判断左右子树。并且分别递归左右子树
3.递归的出口是pre的长度为0 (没有子树)或为1 (只有一个元素) --都要返回

代码

import java.util.*;
/**
 * Definition for binary tree
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
        //出口
        if(pre.length == 0){
            return null;
        }  
        int rootVal = pre[0];
         //数组长度仅为1的时候就要处理
        if(pre.length == 1){
            return new TreeNode(rootVal);
        }
        TreeNode root = new TreeNode(rootVal);
        int rootIndex = 0;
        for(int i =0;i<in.length;i++){
            if(in[i]==rootVal){
                rootIndex = i;
                break; 
            }
        }  
        //递归,假设root的左右子树都已经构建完毕,那么只要将左右子树安到root左右即可
        
        //这里注意Arrays.copyOfRange(int[],start,end)是[)的区间
        root.left = reConstructBinaryTree(Arrays.copyOfRange(pre,1,rootIndex+1),Arrays.copyOfRange(in,0,rootIndex));
        root.right = reConstructBinaryTree(Arrays.copyOfRange(pre,rootIndex+1,pre.length),Arrays.copyOfRange(in,rootIndex+1,in.length));
        return root;
    }
}

总结

1.注意Arrays.copyOfRange(int[],start,end)是[)的区间


扩展:根据层序遍历及中序遍历重建二叉树 并且输出叶子节点和先序遍历 及后序遍历结果

题目描述
给定二叉树T(树深度不超过H<=10,深度从1开始,节点个数N<1024,节点编号1~N)的层序和中序遍历,输出T从左向右叶子节点以及树先序和后序遍历序列
输入描述:
输入两行,分别代表层序和中序遍历结果,节点编号按单个空格分开
输出描述:
依次输出 从左向右叶子节点 ,先序, 后序 遍历 。 节点编号按空格分开
示例1
输入
复制
3 5 4 2 6 7 1
2 5 3 6 4 7 1
输出
复制
2 6 1
3 5 2 4 6 7 1
2 5 6 1 7 4 3

思路

1.第一步建树:先根据层序遍历及中序遍历的部分找到每个子树的root。然后再递归按找root节点方法建左子树和右子树。
2.建树完成后,直接打印所需的结点。

代码

//用递归重建子树 通过层序和中序
 

/**
 * 根据中序遍历和层次遍历重建一棵二叉树
 * 中序遍历可以确定左子树和右子树的范围
 * 层次遍历可以确定在一个范围的子树中的层级关系
 * 故这二者的序列给定就一定可以唯一的确定一棵二叉树
 */
import java.util.*;
public class Main{
    public static class TreeNode{
        private int val;
        private TreeNode left;
        private TreeNode right;
        public  TreeNode(int x){
            this.val = x;
        }
    }
    public static TreeNode parseTree(int[] level,int[] in){
        return parseDT(level,in,0,in.length-1);
    }
    public static TreeNode parseDT(int[] level,int[] in,int start,int end){
        int rootIndex = findRoot(level,in,start,end);
        if(rootIndex==-1){
            return null;
        }
        TreeNode root = new TreeNode(in[rootIndex]);
        root.left = parseDT(level,in,start,rootIndex-1);
        root.right = parseDT(level,in,rootIndex+1,end);
        return root;
    }
    public static int findRoot(int[] level,int[] in,int start,int end){
        for(int i =0;i<level.length;i++){
            for(int j=start;j<=end;j++){
                if(level[i]==in[j]){
                    return j;
                }
            }
        }
        return -1;
    }
    //如果当前节点的左右子树都空,则是叶子节点,打印后直接返回
    public static void printLeaf(TreeNode tree){
        if(tree==null){
            return;
        }
        if(tree.left==null&&tree.right==null){
            System.out.print(tree.val+" ");
            return;
        }
        printLeaf(tree.left);
        printLeaf(tree.right);
    }
    
    public static void printPre(TreeNode tree){
        if(tree==null){
            return;
        }
        System.out.print(tree.val+" ");
        printPre(tree.left);
        printPre(tree.right);
    }
    
    public static void printPost(TreeNode tree){
        if(tree==null){
            return;
        }
        printPost(tree.left);
        printPost(tree.right);
        System.out.print(tree.val+" ");
    }
    
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        String[] a = sc.nextLine().split(" ");
        String[] b = sc.nextLine().split(" ");
        int[] level = new int[a.length];
        int[] in = new int[b.length];
        for(int i =0;i<a.length;i++){
            level[i] = Integer.parseInt(a[i]);
            in[i] = Integer.parseInt(b[i]);
        }
        
        TreeNode tree = parseTree(level,in);
        printLeaf(tree);
        System.out.println();
        printPre(tree);
        System.out.println();
        printPost(tree); 
    }
}





总结

1.写代码最好能按函数划分 最好简洁明了

扩展:前序跟中序 得到后序遍历并打印

在这里插入图片描述

代码

import java.util.*;

public class Main{
    public static class TreeNode{
        private char val;
        private TreeNode left;
        private TreeNode right;
        public TreeNode(char x){
                this.val = x;
            }
        }
        public static TreeNode parseTree(char[] pre,char[] in){
            if(pre.length == 0){
                return null;
            }
            char rootVal = pre[0];
            if(pre.length == 1){
                return new TreeNode(rootVal);
            }
            int rootIndex=-1;
            for(int i =0;i<in.length;i++){
                if(in[i]==rootVal){
                    rootIndex=i;
                    break; 
                }
            }
            TreeNode root = new TreeNode(rootVal);
            root.left = parseTree(Arrays.copyOfRange(pre,1,rootIndex+1),Arrays.copyOfRange(in,0,rootIndex));
            root.right = parseTree(Arrays.copyOfRange(pre,rootIndex+1,pre.length),Arrays.copyOfRange(in,rootIndex+1,in.length));
            return root;
        }
        
        public static void post(TreeNode tree){
            if(tree==null){
                return;
            }
            post(tree.left);
            post(tree.right);
            System.out.print(tree.val);
        }
        
        
        public static void main(String[] args){
            Scanner sc = new Scanner(System.in);
            String[] input = sc.nextLine().split(" ");
            char[] pre = input[0].toCharArray();
            char[] in = input[1].toCharArray(); 
            TreeNode tree = parseTree(pre,in);
            post(tree);
        }
 
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值