【数据结构(八)上】二叉树经典习题

❣博主主页: 33的博客❣
▶文章专栏分类: Java从入门到精通◀
🚚我的代码仓库: 33的代码仓库🚚
🫵🫵🫵关注我带你学更多数据结构的知识

目录

  • 1.前言
  • 2.经典习题
    • 2.1相同的树
    • 2.2另一棵子树
    • 2.3翻转二叉树
    • 2.4平衡二叉树
    • 2.5对称二叉树
    • 2.6二叉树的构建及遍历
    • 2.7二叉树的分层遍历
  • 3.总结

1.前言

在上一篇文章中,博主主要介绍了树与二叉树的基本概念、二叉树概念及特性、遍历方式自己实现一棵二叉树,在这篇文章中,博主将继续与大家分享二叉树经典习题。

2.经典习题

2.1相同的树

给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同:OJ链接
解题思路

递归思想:
1.如果p为空,q为空,那么就是两颗空树肯定相等
2.如果一个树为空另一棵树不为空那么一定不相等
3.如果都不为空,值相同才相等。
4.在递归判断左子树是否相等,右子树是否相等,只有左右子树都相等才是相同的树

class Solution {
    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;
      }
  }
    public boolean isSameTree(TreeNode p, TreeNode q) {
         if(p==null&&q==null){
             return true;
         }
         //p、q有一个为空
         if(p==null&&q!=null||p!=null&&q==null){
             return false;
         }
         //两个都不为空,不相等
         if(p.val!=q.val){
             return false;
         }
         //两个都不为空且p=q
         return isSameTree(p.left,q.left)&&isSameTree(p.right,q.right);
    }
}

2.2另一棵子树

给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树:OJ链接
解题思路

递归思想
1.如果其中一个为null那么就不是子树
2.如果是两棵相同的树,那么就为一定为子树
3.再递归看sub是否为左子树的子树,右子树的子树,如果都不是,则返回false

public boolean isSubtree(TreeNode root, TreeNode subRoot) {
        if(root == null &&subRoot!=null|| subRoot == null&&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;
    }  

2.3翻转二叉树

给你一棵二叉树的根节点 root ,翻转这棵二叉树:OJ链接
解题思路

1.判断是否为空树,判断这棵树是否只有根节点
2.再交换左右子树

public TreeNode invertTree(TreeNode root) {
         if(root==null||root.left==null&&root.right==null){
            return root;
        }
        TreeNode tmp= root.left;
        root.left=root.right;
        root.right=tmp;
        invertTree(root.left);
        invertTree(root.right);
        return root;
    }

2.4平衡二叉树

给定一个二叉树,判断它是否是 平衡二叉树(左右子树相差不超过1):OJ链接
解题思路

递归思想
1.先求一个树深度
2.求左子树的深度,再求右子树的深度,相差>1则不平衡
3.并且左子树和右子树的每一个个小树都要平衡

public boolean isBalanced(TreeNode root) {
        if(root==null){
            return true;
        }
        int left=MaxLength(root.left);
        int right=MaxLength(root.right);
        if (Math.abs(left-right)<=1&&isBalanced(root.right)&&isBalanced(root.left)){
            return true;
        }else {
            return false;
        }
    }
    public int MaxLength(TreeNode root){
        if (root==null){
            return 0;
        }
        int Left=MaxLength(root.left);
        int Right=MaxLength(root.right);
        return Left>Right?Left+1:Right+1;
    }

我们观察以上代码,我们发现在求长度的时候已经遍历了一次二叉树,但在求是否平衡的时候,每次递归又会再求高度再遍历数组,效率非常低。那有能不能在求高度的时候就可以判断子树是否平衡呢?答案是可以的,如下:

当求高度的时候先先判断左子树和右子树只差是否小于1,如果小于1就返回-1,就不会再往递归了。

public boolean isBalanced(TreeNode root) {
        if(root==null){
            return true;
        }
        return MaxLength(root)>0;
    }
    public int MaxLength(TreeNode root){
        if (root==null){
            return 0;
        }
        int Left=MaxLength(root.left);
        int Right=MaxLength(root.right);
       if(Left>=0&&Right>=0&&Math.abs(Left-Right)<=1){
           return Math.max(Left,Right)+1;
       }else return -1;
    }

2.5对称二叉树

给你一个二叉树的根节点 root , 检查它是否轴对称:OJ链接
解题思路

1.判断root是否为null
2.比较左子树和右子树是否对称
3.若其中一棵树为null,那么不对称,若都为null则对称
4.再判断,左子树的左节点是否等于右子树的右节点&&左子树的右节点等于右子树的左节点,依次递归。

class Solution {
        public boolean isSymmetric(TreeNode root){
        if(root==null){
            return true;
        }else {
            return isSymmetric(root.left,root.right);
        }
    }
    public boolean isSymmetric(TreeNode L,TreeNode R){
        if(L==null&&R==null){
            return true;
        }
        if(L==null&&R!=null||L!=null&&R==null){
                return false;
        }
        if(L.val!= R.val){
            return false;
        }
      return isSymmetric(L.left,R.right)&&isSymmetric(L.right,R.left);
    }
}

2.6二叉树的构建及遍历

读入用户输入的一串先序遍历字符串,根据此字符串建立一个二叉树:OJ链接

解题思路

1.遍历字符串,不为#,就new一个Node,但在遍历字符串的时候,我们要把i设置为成员变量防止每次递归后i从0开始
2.遍历二叉树中序输出

class TreeNode{
    char val;
    TreeNode left;
    TreeNode right;

    public TreeNode(char val) {
        this.val = val;
    }
}
public class Main {
    static int i=0;
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        while (in.hasNextLine()) { // 注意 while 处理多个 case
            String str=in.nextLine();
            TreeNode root= createTree(str);
            inOrder(root);
        }
    }
    public static TreeNode createTree(String str) {
//        for (int i=0;i<str.length();i++) {
//            char ch = str.charAt(i);i每次则从0开始
        TreeNode root=null;
        if(str.charAt(i)!='#'){
            root=new TreeNode(str.charAt(i));
            i++;
            root.left=createTree(str);
            root.right=createTree(str);
        }else {
            i++;//不要担心i超出字符串长度的问题
        }
        return root;
    }
    public static void inOrder(TreeNode root){
        if(root==null){
            return ;
        }
        inOrder(root.left);
        System.out.print(root.val+" ");
        inOrder(root.right);
    }
}

2.7二叉树的分层遍历

分层遍历二叉树:OJ链接
解题思路

我们需要借助队列来实现,当root不为null时,那么我们将root入队,再将它出队打印,出对的时候我们添加左子树,添加右子树,循环上述操作,直到独队列为空。

public void order(TreeNode root){
        Queue<TreeNode> queue=new LinkedList<>();
        if(root==null){
            return;
        }
        queue.offer(root);
        while (!queue.isEmpty()){
            TreeNode cur=queue.poll();
            System.out.println(cur.val+" ");
            if(cur.left!=null){
                queue.add(cur.left);
            }
            if (cur.right!=null){
                queue.add(cur.right);
            }
        }

    }

除了递归的方式,还可以用非递归的方式:

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

3.总结

在这篇文章中,博主主要分享了比较容易的一些二叉树题目,我们发现在做二叉树的习题时,大多都有用到递归思想,因为二叉树的子树本身也是一棵二叉树,所以当同学们遇到关于二叉树的问题时,可以往递归方向思考。在下一篇文章中,将继续和大家分享二叉树中比较复杂的题目。

下期预告:二叉树经典习题(下)

版权声明:本文为博主作者:PU-YUHAN原创文章,版权归属原作者,如果侵权,请联系我们删除!

原文链接:https://blog.csdn.net/weixin_69049913/article/details/137785920

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
扎眼的阳光的头像扎眼的阳光普通用户
上一篇 2024年5月6日
下一篇 2024年5月6日

相关推荐