当前位置: 首页 > news >正文

数据结构之**二叉树**超全秘籍宝典2

文章目录

  • *1. 前言*
  • *2. 正文*
      • 1. 二叉树的练习题
  • *3. 结语*

“你的每一分耕耘,都藏着未来的收获与惊喜”

1. 前言

本文主要围绕链式二叉树的习题展开,请大家跟进小编的步伐!! 🌹🌹🌹


2. 正文

1. 二叉树的练习题

  1. 检查两棵树是否为相同的树,首先判断是否为相同的树需要两点,
    (1)结构相同
    (2)节点具有相同的值
    在这里插入图片描述根据图上的思路我们的代码很简单就完成了
class Solution {public boolean isSameTree(TreeNode p, TreeNode q) {if(p!=null&&q==null|| p==null&&q!=null){return false;}if(p==null&&q==null){return true;}if(p.val!= q.val){return false;}return isSameTree(p.left,q.left)&&isSameTree(p.right,q.right);}
}

这里注意一点 第二个if语句与第三个if语句的顺序不能交换!!先判断当前节点是否为空再判断值


  1. 是否为另一棵树的子树
    在这里插入图片描述
    我们用代码来完善
    在这里插入图片描述注意这里必须要讨论root==null的情况,root是在遍历树,所以会出现root为空的情况,如果root为null还没有匹配子树,那么就return false
    在这里插入图片描述这里我们还需要用到第一题的方法,如果根结点与子树相同,则返回true,
    不相同再判断左子树与子树是否相同,采用递归的思想
   public boolean isSubtree(TreeNode root, TreeNode subRoot) {if (root==null){return false;}if(isSameTree(root,subRoot)) return true;if(isSubtree(root.left,subRoot)) return true;if(isSubtree(root.right,subRoot)) return true;return false;}

  1. 翻转二叉树
    在这里插入图片描述对于这个操作的实现还是很简单的
   public TreeNode invertTree(TreeNode root) {if(root==null){return null;}TreeNode tmp=root.left;root.left=root.right;root.right=tmp;invertTree(root.left);invertTree(root.right);return root;}

  1. 对称二叉树,判断一棵树是否为对称二叉树我们需要得知root.left 与 root.right是否为对称的
    在这里插入图片描述
    首先我们可以先写一个专门判断二叉树的左子树leftTree与右子树rightTree是否为对称的方法
    在这里插入图片描述
    之后我们直接调用这个方法,就可以完成代码
 public boolean isSymmetric(TreeNode root) {if(root==null){return true;}return isSymmetricChild(root.left, root.right);}public boolean isSymmetricChild(TreeNode leftTree,TreeNode rightTree){if(leftTree!=null&&rightTree==null || leftTree==null&&rightTree!=null){return false;}if(rightTree==null&&leftTree==null){return true;}if(leftTree.val!=rightTree.val){return false;}return isSymmetricChild(leftTree.left,rightTree.right)&&isSymmetricChild(leftTree.right,rightTree.left);}

  1. 平衡二叉树,什么是平衡二叉树?平衡二叉树是指每一个节点的左子树高度与右子树的高度的差值<=1 ,注意是每一个结点
    ****在上篇博客的学习中,我们已经学会了如何求树的高度
    在这里插入图片描述我们只需要在这个基础上完善代码即可
class Solution {public boolean isBalanced(TreeNode root) {if(root==null){return true;}int leftHeight=getHeight(root.left);int rightHeight=getHeight(root.right);return Math.abs(leftHeight-rightHeight)<=1&&isBalanced(root.left)&&isBalanced(root.right);}private int getHeight(TreeNode root){if(root==null){return 0;}int leftHeight=getHeight(root.left);int rightHeight=getHeight(root.right);return Math.max(leftHeight,rightHeight)+1;}
}

紧贴我们的思路!!

下面我们关注一下这个代码的时间复杂度,时间复杂度为O(N^2),因为每一次求树的高度都要重新从头遍历,我们该如何让这个代码的实现达到时间复杂度为O(N)呢!? 也就是只遍历一次树即可
在这里插入图片描述我们在return前增加了一串代码,如果左树右树高度之差大于1了,那么return -1,这里我们需要接收一下-1
在这里插入图片描述如果左树拿到了return的值且为-1,那么我直接让左树返回-1
在这里插入图片描述
这里有的小伙伴就会觉得代码已经完善了,可是我们少考虑了一种情况,如果rightHeight也为负数,leftHeight==0,那么0-(-1)=1,这个代码就有问题了!!

class Solution {public boolean isBalanced(TreeNode root) {if(root==null){return true;}return getHeight(root)>0;}private int getHeight(TreeNode root){if(root==null){return 0;}int leftHeight=getHeight(root.left);if(leftHeight<0){return -1;}int rightHeight=getHeight(root.right);if(Math.abs(leftHeight - rightHeight) > 1 || rightHeight<0){return -1;}else{return Math.max(leftHeight,rightHeight)+1;}}
}

当然这里的getHeight方法也可以这样写

    private int getHeight(TreeNode root){if(root==null){return 0;}int leftHeight=getHeight(root.left);if(leftHeight<0){return -1;}int rightHeight=getHeight(root.right);if(Math.abs(leftHeight - rightHeight) <2&& rightHeight >= 0){return Math.max(leftHeight,rightHeight)+1;}else{return -1;}}

注意 “||”和“&&”区别


  1. 二叉搜索树与双向链表,这里我们的目的是输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。
    首先什么二叉搜索树?二叉搜索树就是 左子树值<根结点值<右子树值
    在这里插入图片描述我们先完成中序遍历这个方法
    在这里插入图片描述下面我们看如何将二叉树转换为双向链表
    在这里插入图片描述

在这里插入图片描述
这样写的话,经历每一次循环root.left永远为null,可见不行!
在这里插入图片描述
利用一个prev的变量,将prev的right域指向循环后的root,然后让prev指向root,顺序不能变
在这里插入图片描述这里还要注意prev如果为null的话就没有right域,我们再看这个代码是否有问题呢?
这里注意!!prev域不能定义在方法里,每次递归这个方法会重新给prev赋值为null
我们的要求是返回链表的头节点,这里我们传入 pRootOfTree最后它的位置仍然在根结点上,所以我们要定义一个头指针head,让head走到最左边!下面我们完善代码

    public TreeNode Convert(TreeNode pRootOfTree) {if (pRootOfTree == null) return null;ConvertChild(pRootOfTree);TreeNode head = pRootOfTree;while (head.left != null) {head = head.left;}return head;}private TreeNode prev=null;private void ConvertChild(TreeNode root) {if (root == null) {return ;}ConvertChild(root.left);root.left = prev;if (prev != null) {prev.right = root;}prev = root;ConvertChild(root.right);}

这样我们的代码才完善!


  1. 二叉树的构建和遍历,本题的意思是输入 ABC##DE#G##F### 其中“#”表示的是空格,空格代表空树,建立后再进行中序遍历

    我们可以先搭框架,先完成中序遍历的方式
    在这里插入图片描述下面我们看看应该如何去创建这棵树

在这里插入图片描述我们可以遍历传入的字符串,如果遇到非‘#’那么就创造一个新的节点,i++,如果遇到‘#’那么直接让i++即可
在这里插入图片描述我们这里让i作为一个静态的成员变量,i 不能为局部变量,因为i的值是在改变的基础上继续变化的,当然静态的变量也有不好之处,如果传入的字符串太大则不行,所以这里可以不用static修饰但是调用方法时要用类的引用调用。

 class Main {static class  TreeNode{TreeNode left;TreeNode right;char val;public TreeNode(char val) {this.val = val;}}public static void main(String[] args) {Scanner in = new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) {String str=in.nextLine();TreeNode root=creatTree(str);inOrder(root);}}public static int i=0;public static TreeNode creatTree(String str){TreeNode root=null;if(str.charAt(i)!='#'){root=new TreeNode(str.charAt(i));i++;root.left=creatTree(str);root.right=creatTree(str);}else{i++;}return root;}public static void inOrder(TreeNode root){if(root==null){return;}inOrder(root.left);System.out.print(root.val+" ");inOrder(root.right);}
}

这样这个方法就完成了


  1. 二叉树的层序遍历,题目中出现了我们之前遇到的二维数组,我们要以二维数组的方式进行输出,其中每一行的一维数组代表二叉树的各个元素,在完成这道题之前,我们先来看看普通的层序遍历应该如何去做呢?
    对于层序遍历,我们可以不使用递归来实现,我们需要引入队列这个数据结构去实现我们的操作
    在这里插入图片描述
    我们可以根据图完成代码
  public void levelOrder(TreeNode root){Queue<TreeNode> queue=new LinkedList<>();queue.offer(root);while(!queue.isEmpty()){TreeNode cur=queue.poll();System.out.println(cur.val+" ");if(cur.left!=null){queue.offer(cur.left);}if(cur.right!=null) {queue.offer(cur.right);}}}

只要队列不为空,我就继续放,为空后我的二叉树元素就被全部打印了!

下面我们来看这道题,与上述不一样的是,我们要返回一个二维数组,下面我们思考如何结合二维数组完成二叉树的层序遍历?二维数组是由一个个一维数组组成,我们只需要把每一层元素放到一个一维数组中即可
在这里插入图片描述我们直接来实现一下

   public List<List<Integer>> levelOrder(TreeNode root) {List<List<Integer>> ret=new ArrayList<>();if(root==null){return ret;}Queue<TreeNode> queue=new LinkedList<>();queue.offer(root);while(!queue.isEmpty()){List<Integer> list=new ArrayList<>();int size=queue.size();while(size!=0){TreeNode cur=queue.poll();list.add(cur.val);if(cur.left!=null){queue.offer(cur.left);}if(cur.right!=null) {queue.offer(cur.right);}size--;}ret.add(list);}return ret;}

这里注意,每次的顺序表都要放在size循环中,每次cur=queue.poll()也要放入循环之中,因为如果在外就取不到值了


  1. 判断一棵树是不是完全二叉树
    在这里插入图片描述
    我们思考什么是完全二叉树?
    在这里插入图片描述
    这就是一个完全二叉树,我们还是利用队列来实现,那么应该如何实现呢?
    在这里插入图片描述
    我们来完善一下代码
    在这里插入图片描述
    首先这里与我们层序遍历二叉树很相似,我们只要碰见null就跳出循环
    在这里插入图片描述跳出循环后,我们执行这部分代码,判断当前队列是否全为null,这样我们的代码就完成了
   public 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 peek= queue.peek();if (peek!=null){return false;}queue.poll();}return true;}

以上就是本篇博客的全部练习,所有代码在这🌹


3. 结语

以上就是本文主要的内容,我们主要实现了二叉树的很多练习题,接下来还会有一部分练习题,以及顺序表实现二叉树的知识,请大家敬请期待!!有不明白的地方可以留言小编会回复,希望读者们多提建议,小编会改正,共同进步!谢谢大家。🌹🌹🌹

http://www.dtcms.com/a/572731.html

相关文章:

  • win32k!ProcessKeyboardInput函数分析---登录界面ctrl+alt+del键的处理
  • 网站版权信息修改wordpress釆集插件破解
  • Springcloud_day01
  • 理解提示词Prompt
  • iOS 抓不到包怎么办?工程化排查与替代抓包方案(抓包/HTTPS/Charles代理/tcpdump)
  • 告别密码和防火墙——将 Git 仓库从 HTTPS 切换到 SSH 连接
  • Fiddler抓包工具详解,HTTP/HTTPS抓包、代理设置与调试技巧一站式教程(含实战案例)
  • Go语言爬虫:采集百度热榜并将拼装后的json写入txt文件
  • 图模式分析:PyTorch Compile组件解析
  • Microsoft Fabric - 试一下在前端应用中使用 GraphQL API去连接Lakehouse
  • 测试套件缩减方法
  • Oracle SQL Developer设置打开表的时候如何是新窗口中打开
  • 新开传奇网站刚开一秒甘南网站设计公司
  • postman 安装教程
  • 网站建站流程图简单工程承包合同
  • 【Linux系统编程】进程概念(三)进程状态
  • 360极速浏览器 安装猫抓插件的方法
  • 面向对象(上)-递归方法的使用
  • PPPOE实验
  • 【LeetCode 经典题解】:队列与栈的双向模拟——从原理到代码详解
  • 学习笔记5
  • 多线程 忙等待和线程等待的区别
  • 网站建设运维合同汽车城网站建设方案
  • 建立网站需要什么设备网站制作对公司的作用
  • C++类与对象:从入门到精通
  • UniApp 全局通知功能实现
  • uni-app开发安卓app时控制屏幕常亮不息屏
  • uniapp 小程序引入 uview plus 框架,获得精美的UI框架
  • 在被窝里使用笔记本电脑,容易损坏键盘?
  • Unix Domain Socket:构建高效本地进程间通信的完整指南