二叉树高频题精讲 | 从入门到熟练掌握二叉树操作3(上难度了)

本系列可作为JAVA学习系列的笔记,文中提到的一些练习的代码,小编会将代码复制下来,大家复制下来就可以练习了,方便大家学习。

点赞关注不迷路!您的点赞、关注和收藏是对小编最大的支持和鼓励! 

系列文章目录

JAVA初阶---------已更完

JAVA数据结构 DAY1-集合和时空复杂度

JAVA数据结构 DAY2-包装类和泛型

JAVA数据结构 DAY3-List接口

JAVA数据结构 DAY4-ArrayList

JAVA数据结构 DAY5-LinkedList

JAVA数据结构 DAY6-栈和队列

JAVA数据结构 DAY7-二叉树

JAVA数据结构 DAY8-堆

JAVA数据结构 DAY9 equals、Comparable、Comparator 与 PriorityQueue 深度解析

JAVA数据结构 DAY10-排序

JAVA数据结构 DAY11-Set和Map


拓展目录

手把手教你用 ArrayList 实现杨辉三角:从逻辑推导到每行代码详解

链表高频 6 题精讲 | 从入门到熟练掌握链表操作

二叉树高频题精讲 | 从入门到熟练掌握二叉树操作

二叉树高频题精讲 | 从入门到熟练掌握二叉树操作2

二叉树高频题精讲 | 从入门到熟练掌握二叉树操作3

Java 中的 hashCode () 与 equals () 核心原理、契约规范、重写实践与面试全解

Set&Map高频题精讲 | 从入门到熟练掌握


目录

目录

系列文章目录

目录

1.从前序与中序遍历序列构造二叉树

2.从后序与中序遍历序列构造二叉树

3.根据二叉树创建字符串

4.二叉树前序非递归遍历实现

5.二叉树后序非递归遍历实现

6.二叉树后序非递归遍历实现

总结


前言

小编作为新晋码农一枚,会定期整理一些写的比较好的代码,作为自己的学习笔记,会试着做一下批注和补充,如转载或者参考他人文献会标明出处,非商用,如有侵权会删改!欢迎大家斧正和讨论!

本节,我将分享一下二叉树的习题部分,以及思路详解,在力扣 的运行环境,每一题将会附上练题链接,大家点击即可练习!

1.从前序与中序遍历序列构造二叉树

给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。

题目链接:
105. 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode)

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    
    //给定两个整数数组 preorder 和 inorder ,
    //其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        return build(preorder,0,preorder.length-1,inorder,0,inorder.length-1);
    }
    public TreeNode build(int[] preorder,int prestart,int preend,int[] inorder,int instart,int inend){
        if(prestart>preend||instart>inend){
            return null;
        }
        int val=preorder[prestart];
        TreeNode root=new TreeNode(val);
        int rootindex=0;
        for(int i=instart;i<inorder.length;i++){
            if(val==inorder[i]){
                rootindex=i;
                break;
            }
        }
        int leftsize=rootindex-instart;
        root.left=build(preorder,prestart+1,prestart+leftsize,inorder,instart,rootindex-1);
        root.right=build(preorder,prestart+leftsize+1,preend,inorder,rootindex+1,inend);
        //✅ 左子树 先序区间
        //preStart + 1 ~ preStart + leftSize 跳过根(+1),往后数 leftSize 个,就是左子树全部!
        //✅ 右子树 先序区间
        //preStart + leftSize + 1 ~ preEnd  左子树结束后,剩下的全是右子树!
        //✅ 左子树 中序区间
        //inStart ~ rootIndex - 1  根左边全部是左子树!
        //✅ 右子树 中序区间 
        //rootIndex + 1 ~ inEnd  根右边全部是右子树!
        return root;
    }
}

2.从后序与中序遍历序列构造二叉树

给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。

题目链接:

106. 从中序与后序遍历序列构造二叉树 - 力扣(LeetCode)

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    //给定两个整数数组 inorder 和 postorder ,
    // 其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。
    //给定两个整数数组 preorder 和 inorder ,
    //其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        return build(inorder,0,inorder.length-1,postorder,0,postorder.length-1);
    }
    public TreeNode build(int[] inorder,int instart,int inend,int[] postorder,int poststart,int postend){
        if(poststart>postend||instart>inend){
            return null;
        }
        int val=postorder[postend];
        TreeNode root=new TreeNode(val);
        int rootindex=0;
        for(int i=instart;i<=inend;i++){
            if(val==inorder[i]){
                rootindex=i;
                break;
            }
        }
        int leftsize=rootindex-instart;
        root.left=build(inorder,instart,rootindex-1,postorder,poststart,poststart+leftsize-1);
        root.right=build(inorder,rootindex+1,inend,postorder,poststart+leftsize,postend-1);
        return root;
    }
}

3.根据二叉树创建字符串

给你二叉树的根节点 root ,请你采用前序遍历的方式,将二叉树转化为一个由括号和整数组成的字符串,返回构造出的字符串。

空节点使用一对空括号对 "()" 表示,转化后需要省略所有不影响字符串与原始二叉树之间的一对一映射关系的空括号对。

题目链接:

606. 根据二叉树创建字符串 - 力扣(LeetCode)

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    //前序遍历顺序:根节点 → 左子树 → 右子树。
    //节点处理规则:
    //根节点直接拼接数字。
    //若存在左子树或右子树,需要用括号包裹子树:
    //左子树:无论是否为空,只要存在右子树,就必须用 () 表示空左子树;否则可以省略。
    //右子树:只有当右子树非空时,才用括号包裹;空右子树直接省略。
   
    public String tree2str(TreeNode root) {
        //空节点
       if(root==null){
           return "";
       }
       //左右都无
       if(root.left==null&&root.right==null){
           return Integer.toString(root.val);
       }
       //左无
       if (root.left==null){
           return root.val+"()"+"("+tree2str(root.right)+")";
       }
        //有左,没有右 ← 加上这一行就完美!
         if(root.right==null){
             return root.val+"("+tree2str(root.left)+")";
         }
        //左右都有
           return root.val+"("+tree2str(root.left)+")"+"("+tree2str(root.right)+")";

    }
}

4.二叉树前序非递归遍历实现

给你二叉树的根节点 root ,返回它节点值的 前序 遍历。

题目链接:

144. 二叉树的前序遍历 - 力扣(LeetCode)

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
   //二叉树先序遍历的非递归方法
    //先压右,再压左!因为栈是后进先出!
    //前序:根 → 左 → 右
    //栈是后进先出,所以必须先放右孩子,再放左孩子
    //这样弹出来的顺序才是:根 → 左 → 右
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> ret=new ArrayList<>();
        if(root==null){
            return ret;
        }
        Stack<TreeNode> stack=new Stack<>();
        stack.push(root);
        while(!stack.isEmpty()){
            TreeNode node=stack.pop();
            ret.add(node.val);
            if(node.right!=null){
                stack.push(node.right);
            }
            if(node.left!=null){
                stack.push(node.left);
            }            

        }
        return ret;
    }
}

5.二叉树后序非递归遍历实现

给你二叉树的根节点 root ,返回它节点值的 中序 遍历。

题目链接:

94. 二叉树的中序遍历 - 力扣(LeetCode)

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    //中序遍历:左 → 根 → 右
    //非递归思路(4 句话背会)
    //一路向左,全部入栈(走到最左边)
    //左边走不动了,再出栈
    //出栈时访问(加入结果) → 这就是 “根”
    //立刻转向右子树
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> ret=new ArrayList<>();
        if(root==null){
            return ret;
        }
        Stack<TreeNode> stack=new Stack<>();
        TreeNode cur=root;
        while(cur!=null||!stack.isEmpty()){
            while(cur!=null){
                stack.push(cur);//先入栈 再往左
                cur=cur.left;
                
            }
            //左边全部的节点都入栈

            cur=stack.pop(); //弹出栈顶元素
            ret.add(cur.val); //访问根节点

            cur=cur.right;//访问右节点

        }
        return ret;
    }
}

6.二叉树后序非递归遍历实现

给你二叉树的根节点 root ,返回它节点值的 后序 遍历。

题目链接:

145. 二叉树的后序遍历 - 力扣(LeetCode)

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    //后序 = 根 → 右 → 左 的逆序!
    //用前序思路:先压左、再压右 → 得到顺序:根 → 右 → 左
    //最后把结果反转 → 就是 左 → 右 → 根(后序)
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> ret=new ArrayList<>();
        if(root==null){
            return ret;
        }
        Stack<TreeNode> stack=new Stack<>();
        stack.push(root);
        while(!stack.isEmpty()){
            TreeNode node=stack.pop();
            ret.add(node.val);
            if(node.left!=null){
                stack.push(node.left);
            }
            if(node.right!=null){
                stack.push(node.right);
            }

        }
        Collections.reverse(ret);
        return ret;
    }
}

总结

以上就是今天要讲的内容,本文简单记录了java数据结构,仅作为一份简单的笔记使用,大家根据注释理解,您的点赞关注收藏就是对小编最大的鼓励!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Yvonne爱编码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值