[每日算法0519] 二叉树逐层遍历和通过中序前序获取完整的树

今日题目

  • 二叉树的入门级别题目
  • 递归

今日心得

  • 递归是算法的王道,对于初学者来说确实有点难。这么简单两行代码解决了复杂的问题,同时说明很重要。理解递归的本质是算法进阶的不二法门
  • 二叉树作为面试和工作中最常见的树,从此种下树苗,希望能慢慢成长。
  • 没有想象中那么难,至少可以默写一遍把。会有很多意想不到的困惑和收获。

算法编码

按层级倒叙打印二叉树

package binarytree;

import linklist.ListNode;

import java.util.LinkedList;
import java.util.List;

/**
 * @ClassName PrintTreeNodeByLeveDesc
 * @Description 按倒着的层级逐层打印二叉树的元素
 * @Author kouryoushine
 * @Date 2022/5/19 0:04
 * @Version 1.0
 */
public class PrintTreeNodeByLeveDesc {

    public static void main(String[] args) {
        TreeNode head = new TreeNode(1);
        head.left=new TreeNode(2);
        head.right=new TreeNode(3);
        head.left.left=new TreeNode(4);
        head.left.right=new TreeNode(5);
        head.right.left=new TreeNode(6);
        head.right.right= new TreeNode(7);
        List<List<Integer>> lists = listByleveDesc(head);
        System.out.println(lists);

    }

    public static class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;

        public TreeNode(int v) {
            this.val = v;
        }
    }


    public static  List<List<Integer>> listByleveDesc(TreeNode root) {

        if (root == null) { //边界条件
            return null;
        }
        List<List<Integer>> ans = new LinkedList<>();
        LinkedList<TreeNode> queue = new LinkedList<>();//保存每一层节点的临时队列
        queue.add(root);//初始节点
        while (!queue.isEmpty()) {
            int size=queue.size();
            LinkedList<Integer> curLevel = new LinkedList<>(); //当前level
            for (int i = 0; i < size; i++) {
                TreeNode curAns = queue.poll();//逐个获取层节点
                curLevel.add(curAns.val); // 保存到level的列队中
                if (curAns.left != null) { //把下一层加入队列
                    queue.addLast(curAns.left);
                }
                if (curAns.right != null) {
                    queue.addLast(curAns.right);
                }
            }
            ans.add(0,curLevel);
        }

        return ans;

    }
}

根据前序和中序获取完整二叉树

package binarytree;

import org.omg.PortableInterceptor.INACTIVE;
import sun.reflect.generics.tree.Tree;

import java.util.HashMap;
import java.util.HashSet;

/**
 * @ClassName BuildBinaryTreeByPreAndInArray
 * @Description 通过前序和中序遍历的结果获取整棵树
 * @Author kouryoushine
 * @Date 2022/5/18 22:17
 * @Version 1.0
 */
public class BuildBinaryTreeByPreAndInArray {
    public static class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;

        public TreeNode(int v) {
            this.val = v;
        }
    }

    //经典题目,关键在于对二叉树的理解。如果第一次接触二叉树,凡人是不太可能解答题目的
    // 前序:头左右,我们理解数组分成了,head,left子树,right子树三个互相分割的块
    // 中序,左头油,我们可以理解为,[left,head,right]头结点分割了左右两个数
    //  上面两个是算法常识,所以根据此,我么可以得出抽象的结论。前序和中序遍历结果的左树和右树范围是直到的,
    //  只是需要我们获取到输的层级

    //过程
    //1. 边界条件
    //2. 找到中序的head位置(find)
    //3. 获取前序和中序  left和right范围
    //  - 先序(left=[L1+1,L1+find-L2],right=(L1+find-L2+1,R1)
    //  - 中序(left=[L2,find-1],right=[find+1,R2]


    //主函数
    public static TreeNode buildTree(int [] pre,int [] in){
        //边界条件无法生成一棵树
        if(pre==null || in == null || pre.length!=in.length){
            return null;
        }

       return f(pre,0,pre.length-1,in,0,in.length-1);
    }


    //定一个递归函数,通过前中序便利结果不断缩小树的范围,获取一棵树,通过head返回回来
    public static TreeNode f(int [] pre,int L1,int R1,int [] in ,int L2,int R2){

        if(L1>R1){
            return null;
        }

        TreeNode head = new TreeNode(pre[L1]);  //前序的第一个一定是头结点
        if(L1==R1){
            return head;  //只有一个节点直接返回
        }

        int find=0;//中序遍历中,head位置
        while (in[find]!=pre[L1]){
            find++;
        }
        //  - 先序(left=[L1+1,L1+find-L2],right=(L1+find-L2+1,R1)
        //  - 中序(left=[L2,find-1],right=[find+1,R2]
        head.left=f(pre,pre[L1+1],pre[L1+find-L2],in,in[L2],in[find-1]);
        head.right=f(pre,pre[L1+find-L2+1],pre[R1],in,in[find+1],in[R2]);
        return head;
    }

    /**
     * 解决方法二
     *
     * 先序遍历的每个节点都认为是头node,只要保存node的下标即可。遍历头部就可以生成整棵树
     */


    //主函数
    public static TreeNode buildTree2(int [] pre,int [] in){
        //边界条件无法生成一棵树
        if(pre==null || in == null || pre.length!=in.length){
            return null;
        }
        HashMap<Integer, Integer> headIndexMap= new HashMap<>();
        for (int i = 0; i < pre.length; i++) {
            headIndexMap.put(pre[i],i);
        }
       return f2(pre,0,pre.length-1,in,0,in.length-1,headIndexMap);
    }


    //定一个递归函数,通过前中序便利结果不断缩小树的范围,获取一棵树,通过head返回回来
    public static TreeNode f2(int [] pre,int L1,int R1,int [] in ,int L2,int R2,HashMap<Integer,Integer> headIndexMap){

        if(L1>R1){
            return null;
        }

        TreeNode head = new TreeNode(pre[L1]);  //前序的第一个一定是头结点
        if(L1==R1){
            return head;  //只有一个节点直接返回
        }

        int find=headIndexMap.get(pre[L1]);//中序遍历中,head位置

        //  - 先序(left=[L1+1,L1+find-L2],right=(L1+find-L2+1,R1)
        //  - 中序(left=[L2,find-1],right=[find+1,R2]
        head.left=f2(pre,pre[L1+1],pre[L1+find-L2],in,in[L2],in[find-1],headIndexMap);
        head.right=f2(pre,pre[L1+find-L2+1],pre[R1],in,in[find+1],in[R2],headIndexMap);
        return head;
    }





}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值