文章目录
- [*1. 前言*](#1. 前言)
- [*2. 正文*](#2. 正文)
-
-
- [1. 二叉树的练习题](#1. 二叉树的练习题)
-
- [*3. 结语*](#3. 结语)
"你的每一分耕耘,都藏着未来的收获与惊喜"
1. 前言
本文主要围绕链式二叉树的习题展开,请大家跟进小编的步伐!! 🌹🌹🌹
2. 正文
1. 二叉树的练习题
- 检查两棵树是否为相同的树,首先判断是否为相同的树需要两点,
(1)结构相同
(2)节点具有相同的值
根据图上的思路我们的代码很简单就完成了
java
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语句的顺序不能交换!!先判断当前节点是否为空再判断值
- 是否为另一棵树的子树

我们用代码来完善
注意这里必须要讨论root==null的情况,root是在遍历树,所以会出现root为空的情况,如果root为null还没有匹配子树,那么就return false
这里我们还需要用到第一题的方法,如果根结点与子树相同,则返回true,
不相同再判断左子树与子树是否相同,采用递归的思想
java
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;
}
- 翻转二叉树
对于这个操作的实现还是很简单的
java
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;
}
- 对称二叉树,判断一棵树是否为对称二叉树我们需要得知root.left 与 root.right是否为对称的

首先我们可以先写一个专门判断二叉树的左子树leftTree与右子树rightTree是否为对称的方法

之后我们直接调用这个方法,就可以完成代码
java
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 ,注意是每一个结点
在上篇博客的学习中,我们已经学会了如何求树的高度
我们只需要在这个基础上完善代码即可
java
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,这个代码就有问题了!!
java
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方法也可以这样写
java
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;
}
}
注意 "||"和"&&"区别
- 二叉搜索树与双向链表,这里我们的目的是输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。
首先什么二叉搜索树?二叉搜索树就是 左子树值<根结点值<右子树值
我们先完成中序遍历这个方法
下面我们看如何将二叉树转换为双向链表


这样写的话,经历每一次循环root.left永远为null,可见不行!

利用一个prev的变量,将prev的right域指向循环后的root,然后让prev指向root,顺序不能变
这里还要注意prev如果为null的话就没有right域,我们再看这个代码是否有问题呢?
这里注意!!prev域不能定义在方法里,每次递归这个方法会重新给prev赋值为null
我们的要求是返回链表的头节点,这里我们传入 pRootOfTree最后它的位置仍然在根结点上,所以我们要定义一个头指针head,让head走到最左边!下面我们完善代码
java
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);
}
这样我们的代码才完善!
-
二叉树的构建和遍历,本题的意思是输入 ABC##DE#G##F### 其中"#"表示的是空格,空格代表空树,建立后再进行中序遍历
我们可以先搭框架,先完成中序遍历的方式
下面我们看看应该如何去创建这棵树
我们可以遍历传入的字符串,如果遇到非'#'那么就创造一个新的节点,i++,如果遇到'#'那么直接让i++即可
我们这里让i作为一个静态的成员变量,i 不能为局部变量,因为i的值是在改变的基础上继续变化的,当然静态的变量也有不好之处,如果传入的字符串太大则不行,所以这里可以不用static修饰但是调用方法时要用类的引用调用。
java
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);
}
}
这样这个方法就完成了
- 二叉树的层序遍历,题目中出现了我们之前遇到的二维数组,我们要以二维数组的方式进行输出,其中每一行的一维数组代表二叉树的各个元素,在完成这道题之前,我们先来看看普通的层序遍历应该如何去做呢?
对于层序遍历,我们可以不使用递归来实现,我们需要引入队列这个数据结构去实现我们的操作

我们可以根据图完成代码
java
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);
}
}
}
只要队列不为空,我就继续放,为空后我的二叉树元素就被全部打印了!
下面我们来看这道题,与上述不一样的是,我们要返回一个二维数组,下面我们思考如何结合二维数组完成二叉树的层序遍历?二维数组是由一个个一维数组组成,我们只需要把每一层元素放到一个一维数组中即可
我们直接来实现一下
java
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()也要放入循环之中,因为如果在外就取不到值了
- 判断一棵树是不是完全二叉树

我们思考什么是完全二叉树?

这就是一个完全二叉树,我们还是利用队列来实现,那么应该如何实现呢?

我们来完善一下代码

首先这里与我们层序遍历二叉树很相似,我们只要碰见null就跳出循环
跳出循环后,我们执行这部分代码,判断当前队列是否全为null,这样我们的代码就完成了
java
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. 结语
以上就是本文主要的内容,我们主要实现了二叉树的很多练习题,接下来还会有一部分练习题,以及顺序表实现二叉树的知识,请大家敬请期待!!有不明白的地方可以留言小编会回复,希望读者们多提建议,小编会改正,共同进步!谢谢大家。🌹🌹🌹