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

Posted 如何在5年薪百万

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[每日算法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;
    







以上是关于[每日算法0519] 二叉树逐层遍历和通过中序前序获取完整的树的主要内容,如果未能解决你的问题,请参考以下文章

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

输入后序和中序,构造二叉树,并输出该二叉树的层序前序中序后序遍历结构;输入后序和中序,构造二叉树,并输出该二叉树的层序前序中序后序遍历结构

二叉树的四种遍历方式以及中序后序前序中序前序后序层序创建二叉树专为力扣刷题而打造

二叉树的四种遍历方式以及中序后序前序中序前序后序层序创建二叉树专为力扣刷题而打造

二叉树的四种遍历方式以及中序后序前序中序前序后序层序创建二叉树专为力扣刷题而打造

中序后续/中序前序构造二叉树