【数据结构】 二叉树面试题讲解->叁

news2025/1/18 18:13:20

文章目录

  • 🌏引言
  • 🌲[根据二叉树创建字符串](https://leetcode.cn/problems/construct-string-from-binary-tree/submissions/)
    • 🐱‍👤题目描述:
    • 🐱‍🐉示例:
      • 📌示例一
      • 📌示例二
    • 🐱‍👓思路解析
    • 🐱‍🏍代码完整实现:
  • 🌴判断一棵树是不是完全二叉树
    • 🐱‍👤题目描述:
    • 🐱‍🐉示例:
    • 🐱‍👓思路解析:
    • 🐱‍🏍完整代码实现:
  • 🎋[二叉树的前序遍历(迭代实现)](https://leetcode.cn/problems/binary-tree-preorder-traversal/)
    • 🐱‍👤题目描述:
    • 🐱‍🐉示例:
    • 🐱‍👓思路解析:
    • 🐱‍🏍代码实现如下:
  • 🍀[二叉树的中序遍历(迭代实现)](https://leetcode.cn/problems/binary-tree-inorder-traversal/description/)
    • 🐱‍👤题目描述:
    • 🐱‍🐉示例:
    • 🐱‍👓思路解析:
    • 🐱‍🏍代码实现:
  • 🎄[二叉树的后续遍历(迭代实现)](https://leetcode.cn/problems/binary-tree-postorder-traversal/description/)
    • 🐱‍👤题目描述:
    • 🐱‍🐉示例:
    • 🐱‍👓思路解析:
    • 🐱‍🏍代码完整实现:
  • ⭕总结

🌏引言

二叉树的操作算法是笔试面试中较为常见的题目。
本文将着重介绍平时面试中常见的关于二叉树的应用题目,马上要进行秋招了。希望对你们有帮助 _😀
在这里插入图片描述

🌲根据二叉树创建字符串

🐱‍👤题目描述:

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

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

/**
 * 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) {
     
    }
}

🐱‍🐉示例:

📌示例一

在这里插入图片描述

📌示例二

在这里插入图片描述

🐱‍👓思路解析

我们可以使用递归的方法得到二叉树的前序遍历,并在递归时加上额外的括号。

会有以下 4种情况:

  • 如果当前节点有两个孩子,那我们在递归时,需要在两个孩子的结果外都加上一层括号;

  • 如果当前节点没有孩子,那我们不需要在节点后面加上任何括号;
    在这里插入图片描述

  • 如果当前节点只有左孩子,那我们在递归时,只需要在左孩子的结果外加上一层括号,而不需要给右孩子加上任何括号;

  • 在这里插入图片描述

  • 如果当前节点只有右孩子,那我们在递归时,需要先加上一层空的括号 ‘()’\text{`()'}‘()’ 表示左孩子为空,再对右孩子进行递归,并在结果外加上一层括号。

  • 在这里插入图片描述

那我们具体应该怎么做呢?

做法如下:

  • 由于我们需要返回一个字符串,我们这里创建一个StringBuilder类的对象stringbuilder来存放我们的字符串
  • 接下来我们创建一个方法tree2strChild用于遍历二叉树,并将二叉树变为字符串
  • 在tree2strChild方法里,我们首先将根节点放入到字符串stringbuilder中
  • 然后对左子树进行判断,若不为null
  • 则字符串添加一个左括号
  • 然后递归左子树
  • 递归完后添加右括号
  • 若为null,且右边不为null
  • 则字符串添加()
  • 接下来判断右子树
  • 若右子树为null
  • 直接返回就好
  • 若不为null
  • 字符串添加左括号
  • 然后递归右树
  • 追后字符串添加右括号即可

🐱‍🏍代码完整实现:

/**
 * 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 null;
        }
        StringBuilder stringBuilder = new StringBuilder();
        tree2strChild(root,stringBuilder);
        return stringBuilder.toString();
    }
    public void tree2strChild(TreeNode t,StringBuilder stringBuilder) {
        if(t == null) {
            return;
        }

        stringBuilder.append(t.val);
        if(t.left != null) {
            stringBuilder.append("(");
            tree2strChild(t.left,stringBuilder);
            stringBuilder.append(")");
        }else {
            //左边为空了
            if(t.right != null) {
                //右边不为空
                stringBuilder.append("()");
            }else {
                //右边为空
                return ;
            }
        }

        if(t.right == null) {
            return;
        }else {
            stringBuilder.append("(");
            tree2strChild(t.right,stringBuilder);
            stringBuilder.append(")");
        }
    }
}

🌴判断一棵树是不是完全二叉树

🐱‍👤题目描述:

给你一棵树让你判断是不是完全二叉树

🐱‍🐉示例:

在这里插入图片描述

🐱‍👓思路解析:

其实这道题与博主前面所讲的层序遍历类似

  • 我们依旧定义一个队列,先将根结点入队
  • 如果队列不为空我们就进入循环
  • 将队列的元素进行出栈并赋给cur变量
  • 如果cur不等于null,我们就将cur的左树和右树进行入队
  • 不用管左树右树是否为null;
  • 如果cur为null则跳出循环

这时候队列元素为
在这里插入图片描述
这时候我可以将队列进行出队,元素全部为null,则为完全二叉树

🐱‍🏍完整代码实现:

    boolean isCompleteTree(TreeNode root){
        if(root == null) {
            return true;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            TreeNode cur = queue.poll();
            if(cur != null) {
                queue.offer(cur.left);
                queue.offer(cur.right);
            }else {
                break;
            }
        }
        while (!queue.isEmpty()) {
            TreeNode tmp = queue.poll();
            if(tmp != null) {
                return false;
            }
        }
        return true;
    }

🎋二叉树的前序遍历(迭代实现)

🐱‍👤题目描述:

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

/**
 * 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) {

    }
}

🐱‍🐉示例:

在这里插入图片描述

🐱‍👓思路解析:

我们创建一个栈来实现迭代的前序遍历

  • 我们用变量cur来进行遍历
  • 首先我们对cur进行判断,若不为null,
  • 则将cur入栈,并将该元素存储在顺序表list里
  • 然后遍历cur的左子树

将上述操作放入一个循环里,循环条件就为cur是否为null;

当cur为null时,我们就将栈中元素进行出栈赋给变量top

并用cur访问top的右子树

上面的操作我们再放入一个外循环里,条件为cur不为null或者栈不为空

🐱‍🏍代码实现如下:

/**
 * 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> list = new ArrayList<>();
        if(root == null) {
            return list;
        }
        TreeNode cur = root;
        Deque<TreeNode> stack = new ArrayDeque<>();
        while (cur != null || !stack.isEmpty()) {
            while (cur != null) {
                stack.push(cur);
                list.add(cur.val);
                cur = cur.left;
            }
            TreeNode top = stack.pop();
            cur = top.right;
        }
        return list;
    }
}

🍀二叉树的中序遍历(迭代实现)

🐱‍👤题目描述:

给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。

/**
 * 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> inorderTraversal(TreeNode root) {
    }
}

🐱‍🐉示例:

在这里插入图片描述

🐱‍👓思路解析:

与前序遍历步骤大致相同

不同的是中序遍历需要先在顺序表内存储左节点

也就是说我们需要先将该节点的左节点全部入栈后,然后再出栈到顺序表内

接下来访问右子树

🐱‍🏍代码实现:

/**
 * 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> inorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        if(root == null) {
            return list;
        }
        TreeNode cur = root;
        Deque<TreeNode> stack = new ArrayDeque<>();
        while (cur != null || !stack.isEmpty()) {
            while (cur != null) {
                stack.push(cur);
                cur = cur.left;
            }
            TreeNode top = stack.pop();
            list.add(top.val);
            cur = top.right;
        }
        return list;
    }
}

🎄二叉树的后续遍历(迭代实现)

🐱‍👤题目描述:

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

/**
 * 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) {
       
    }
}

🐱‍🐉示例:

在这里插入图片描述

🐱‍👓思路解析:

入栈思路与前序遍历和中序遍历思路相同

只是出栈不同

  • 我们首先需要得到栈顶元素,但不出栈,依旧用top表示
  • 如果top右节点为null,则说明top为叶子结点,可以出栈进入到顺序表类
  • 如果不为null,则遍历top的右节点

当然现在的思路还有一个问题,我们可能重复遍历top的右子树,最终程序崩溃

所以我们这里加一个变量pero进行判断,若相等则不再遍历该右节点

🐱‍🏍代码完整实现:

/**
 * 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> list = new ArrayList<>();
        if(root == null) {
            return list;
        }
        TreeNode cur = root;
        TreeNode prev = null;
        Deque<TreeNode> stack = new ArrayDeque<>();
        while (cur != null || !stack.isEmpty()) {
            while (cur != null) {
                stack.push(cur);
                cur = cur.left;
            }
            TreeNode top = stack.peek();
            if(top.right == null || top.right == prev) {
                list.add(top.val);
                stack.pop();
                prev = top;
            }else {
                cur = top.right;
            }
        }
        return list;
    }
}

⭕总结

关于《【数据结构】 二叉树面试题讲解->叁》就讲解到这儿,感谢大家的支持,欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/967272.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

1921. 消灭怪物的最大数量

文章目录 Tag题目来源题目解读解题思路方法一&#xff1a;贪心排序 复杂度分析写在最后 Tag 【贪心】【排序】【数组】 题目来源 1921. 消灭怪物的最大数量 题目解读 dist[i] 是第 i 个怪兽与城市的初始距离&#xff0c;speed[i] 是第 i 个怪兽的移动距离。怪兽的目的是攻击…

Mybatis学习|注解开发、lombok

1.使用注解开发 无需再编写相应的Mapper.xml文件&#xff0c;直接将sql用注解的形式写在Mapper接口的对应方法上即可。 然后因为没有xml文件,所以要在mybatis-config.xml核心配置文件中注册这个Mapper接口&#xff0c;而不用去注册之前的Mapper.xml&#xff0c;这里其实如果用…

04_22 vma(进程下的每个虚拟内存区域查看)对象实战

前言 vma不太懂的可以往前翻 03_008内存映射原理_虚拟内存区域vm_area_struct详解,和mmap系统钓调用及物理内存结构体完全分析 vam 虚拟内存区域 每个进程下有多个vma 这次是查看每个vma的起始地址 结束地址和大小使用 1.进程在用户空间调用mmap也就是上面那个函数。 2.在当前…

一个集成的BurpSuite漏洞探测插件1.2

4、DNSLog查询漏报 注&#xff1a;扫描结束后才会在BurpSuite的Target、Dashboard模块显示高危漏洞&#xff0c;进程扫描中无法进行同步&#xff0c;但可以在插件中查看&#xff08;涉及到DoPassive方法问题&#xff09;。

[足式机器人]Part3 变分法Ch01-2 数学预备知识——【读书笔记】

本文仅供学习使用 本文参考&#xff1a; 《变分法基础-第三版》老大中 《变分学讲义》张恭庆 《Calculus of Variations of Optimal Control Theory》-变分法和最优控制论-Daneil Liberzon Ch01-2 数学基础-预备知识1 1.3.2 向量场的通量和散度1.3.3 高斯定理与格林公式 1.3.2 …

js:创建一个基于vite 的React项目

相关文档 Vite 官方中文文档React 中文文档React RouterRedux 中文文档Ant Design 5.0Awesome React 创建vite react项目 pnpm create vite react-app --template react# 根据提示&#xff0c;执行命令 cd react-app pnpm install pnpm run dev项目结构 $ tree -L 1 . ├─…

java基础-----第九篇

系列文章目录 文章目录 系列文章目录前言一、GC如何判断对象可以被回收前言 一、GC如何判断对象可以被回收 引用计数法:每个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计 数为0时可以回收, 可达性分析法:从 GC Roots 开始向下搜索,搜索所走过的…

SourceTree 使用技巧

参考资料 SourceTree使用教程&#xff08;一&#xff09;—克隆、提交、推送SourceTree的软合并、混合合并、强合并区别SourceTree 合并分支上的多个提交&#xff0c;一次性合并分支的多次提交至另一分支&#xff0c;主分支前进时的合并冲突解决 目录 一. 基础设置1.1 用户信息…

mall :hutool项目源码解析

文章目录 一、mall开源项目1.1 来源1.2 项目转移1.3 项目克隆 二、Hutool工具类库2.1 Hutool 简介 三、源码解析3.1 集成与配置3.1.1 导入依赖3.1.2 添加配置 3.2 核心工具类3.2.1 AnnotationUtil使用&#xff1a;注解工具类3.2.2 BeanUtil使用&#xff1a;JavaBean的工具类3.2…

精品基于SpringCloud实现的电影院购票系统设计-微服务-分布式

《[含文档PPT源码等]精品基于SpringCloud实现的电影院购票系统设计的设计与实现-微服务-分布式》该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程等 软件开发环境及开发工具&#xff1a; 开发语言&#xff1a;Java 框架&#xff1a;springcloud JDK版…

AI:06-基于OpenCV的二维码识别技术的研究

二维码作为一种广泛应用于信息传递和识别的技术,具有识别速度快、容错率高等优点。本文探讨如何利用OpenCV库实现二维码的快速、准确识别,通过多处代码实例展示技术深度。 二维码作为一种矩阵型的条码,广泛应用于各个领域,如商品追溯、移动支付、活动签到等。二维码的快速…

【力扣】416. 分割等和子集 <动态规划、回溯>

【力扣】416. 分割等和子集 给你一个 只包含正整数的非空数组 nums 。请你判断是否可以将这个数组分割成两个子集&#xff0c;使得两个子集的元素和相等。 示例 1&#xff1a; 输入&#xff1a;nums [1,5,11,5] 输出&#xff1a;true 解释&#xff1a;数组可以分割成 [1, 5,…

nmap的使用

目录 nmap简介 主要作用 nmap原理 namp使用 options nmap列举远程机器开放端口 普通扫描 扫描范围端口 对几个端口探测 对所有端口进行探测 指定协议探测端口 扫描对应协议的所有端口 端口状态 nmap识别目标机器上服务的指纹 服务指纹 识别目标机器服务信息 …

Spring 中存取 Bean 的相关注解

目录 一、五大类注解 1、五大类注解存储Bean对象 1.1Controller(控制器储存) 1.2Service(服务存储) 1.3Repository(仓库存储) 1.4Component(组件存储) 1.5Configuration(配置存储) 2、五大类注解小结 2.1为什么要这么多类注解 2.2 五大类注解之间的关系 二、方法注解 1.方法注…

微信小程序编辑器代码格式缩进设置

第一步点击这个编辑器设置&#xff1a; 然后设置tab为空格&#xff0c;并且设置占几个空格&#xff0c;这里是4个空格。 这样就好了&#xff0c;文件保存就会自动设置好缩进格式了。

【Day-27慢就是快】代码随想录-二叉树-二叉树的最小深度

给定一个二叉树&#xff0c;找出其最小深度。 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。 说明: 叶子节点是指没有子节点的节点。 —————————————————————————————————— 1. 递归法 确定单层递归的逻辑&#xff1a; 与最…

3D 碰撞检测

推荐&#xff1a;使用 NSDT场景编辑器快速搭建3D应用场景 轴对齐边界框 与 2D 碰撞检测一样&#xff0c;轴对齐边界框 &#xff08;AABB&#xff09; 是确定两个游戏实体是否重叠的最快算法。这包括将游戏实体包装在一个非旋转&#xff08;因此轴对齐&#xff09;的框中&#…

可扩展的Blender插件开发汇总

成熟的 Blender 3D 插件是令人惊奇的事情。作为 Python 和 Blender 的新手,我经常发现自己被社区中的人们创造的强大的东西弄得目瞪口呆。坦率地说,其中一些包看起来有点神奇,当自我怀疑或冒名顶替综合症的唠叨声音被打破时,很容易想到“如果有人能做出可以做xxx的东西就好…

【数据分享】2012-2022年中国范围的逐年NPP/VIIRS夜间灯光数据(无需转发\免费获取)

在之前的文章中我们分享了2012-2022年全球范围逐年NPP/VIIRS夜间灯光数据&#xff08;可查看之前的文章获悉详情&#xff09;&#xff01;很多小伙伴在拿到数据后&#xff0c;反映数据太大了&#xff0c;有413G&#xff0c;下载非常不方便&#xff01;这个数据的范围是全球的&a…

七、Linux中一些符号的含义和宿主目录的介绍

1、Linux中一些符号的含义 在Linux命令行中&#xff0c;会看到如下一些符号&#xff0c;含义如下。 符号含义. 代表当前目录..代表上一层目录&#xff0c;当前目录的父目录-代表前一个目录&#xff0c;刚才从哪个目录cd过来~代表当前用户的宿主目录/代表根目录$普通用户的命…