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

Java数据结构第十四期:走进二叉树的奇妙世界(三)

专栏:数据结构(Java版)

个人主页:手握风云

目录

一、二叉树OJ练习题

1.1. 相同的树

1.2. 另一棵树的子树

1.3. 翻转二叉树

1.4. 平衡二叉树

1.5. 对称二叉树


一、二叉树OJ练习题

1.1. 相同的树

        判断两棵树是否相同,我们是否只能遍历一遍看结果?看下面的三棵二叉树,上面的树存储的值相同,结构也相同;中间的树存储的值相同,但结构不同;下面的树存储的值不相同。所以我们只遍历一遍看结果不可以。

       我们以相同的方式来遍历两棵二叉树。要判断两棵树结构相同,要么结点同时为空,要么同时不为空。当两个结点都不为空,再去判断结点所存储的值是否相同。先定义两个引用p、q,然后判断根结点是否相同。我们以下图为例,根结点相同、左子树相同且右子树也相同再去判断值相同。如果一个为空,另一个不为空,则结构不同;如果两个引用都不为空,但值不同,也返回false。

完整代码:

class TreeNode{
    int val;
    TreeNode left;
    TreeNode right;

    public TreeNode(){}

    public TreeNode(int val) {
        this.val = val;
    }

    public TreeNode(int val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

/**
 * 时间复杂度O(min(m.n))
 * m为p这棵树的结点,n为q这棵树的结点
 * 结点小的最先遍历完
 */
public class Solution {
    public boolean isSameTree(TreeNode p, TreeNode q){
        if((p != null && q == null) || (p == null && q!= null)){
            return false;
        }

        //上面的if语句不生效,代表要么都为空,要么都不为空
        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);
    }
}
public class Test {
    public static void main(String[] args) {
        Solution solution = new Solution();

        TreeNode Tree1 = new TreeNode(1,new TreeNode(2),null);
        TreeNode Tree2 = new TreeNode(1,null,new TreeNode(2));
        System.out.println(solution.isSameTree(Tree1,Tree2));

        TreeNode Tree3 = new TreeNode(1,new TreeNode(2),new TreeNode(3));
        TreeNode Tree4 = new TreeNode(1,new TreeNode(2),new TreeNode(3));
        System.out.println(solution.isSameTree(Tree3,Tree4));

        TreeNode Tree5 = new TreeNode(1,new TreeNode(2),new TreeNode(1));
        TreeNode Tree6 = new TreeNode(1,new TreeNode(1),new TreeNode(2));
        System.out.println(solution.isSameTree(Tree5,Tree6));
    }
}

1.2. 另一棵树的子树

        一棵树的本身就是它的子树,所以我们要首先判断两棵树是否相同,再去判断subRoot是不是等于root的左子树还是右子树,判断我们可以依照上面讲过的是否是相同的树来判断。

完整代码:

class TreeNode{
    public int val;
    public TreeNode left;
    public TreeNode right;

    public TreeNode(){}

    public TreeNode(int val) {
        this.val = val;
    }

    public TreeNode(int val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

public class Solution {
    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;
    }

    public boolean isSameTree(TreeNode p, TreeNode q) {
        if((p != null && q == null) || (p == null && q!= null)){
            return false;
        }

        //上面的if语句不生效,代表要么都为空,要么都不为空
        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);
    }
}
public class Test {
    public static void main(String[] args) {
        Solution solution = new Solution();

        TreeNode root = new TreeNode(3,new TreeNode(4),new TreeNode(5));
        root.left.left = new TreeNode(1);
        root.left.right = new TreeNode(2);

        TreeNode SubRoot = new TreeNode(4,new TreeNode(1),new TreeNode(2));

        System.out.println(solution.isSubtree(root, SubRoot));
    }
}

1.3. 翻转二叉树

        翻转就是把每一个结点的左右孩子都进行交换(如下图所示)。下图可能有一些抽象,我们可以从内存上对二叉树进行一个翻转。只要root不为空,就对左右结点进行交换。当root遍历完整棵二叉树,就可以进行翻转。

完整代码:

class TreeNode{
    public int val;
    public TreeNode left;
    public TreeNode right;

    public TreeNode(){}

    public TreeNode(int val) {
        this.val = val;
    }

    public TreeNode(int val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

public class Solution {
    public TreeNode invertTree(TreeNode root){
        if(root == null){
            return null;
        }

        if(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;
    }

    public void PrevOrder(TreeNode root){
        if(root == null){
            return;
        }
        System.out.print(root.val+" ");
        PrevOrder(root.left);
        PrevOrder(root.right);
    }
}
public class Test {
    public static void main(String[] args) {
        Solution solution = new Solution();
        TreeNode root = new TreeNode(4,new TreeNode(2),new TreeNode(7));
        root.left.left = new TreeNode(1);
        root.left.right = new TreeNode(3);
        root.right.left = new TreeNode(6);
        root.right.right = new TreeNode(9);
        
        System.out.print("翻转之前:");
        solution.PrevOrder(root);
        System.out.println();
        
        solution.invertTree(root);
        
        System.out.print("翻转之后:");
        solution.PrevOrder(root);
    }
}

1.4. 平衡二叉树

        平衡二叉树是指该树所有节点的左右子树的高度相差不超过1。很明显这道题是涉及到求二叉树深度的问题。实现的逻辑也非常简单:求出每棵子树的高度,如果左子树的高度与右子树的高度之差小于等于1,则是平衡二叉树。我们可以调用之前求二叉树的最大深度的方法来求高度。但还存在一种反例(如下图所示)。下面这棵二叉树就不是平衡二叉树,因为9这个的结点的左右子树高度差为2。那么我们就不能只求一次高度,还需要重复计算高度,那么此时的时间复杂度也会随着增大,O(n^{2})

class TreeNode{
    public int val;
    public TreeNode left;
    public TreeNode right;

    public TreeNode(){}

    public TreeNode(int val) {
        this.val = val;
    }

    public TreeNode(int val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

public class Solution {
    public boolean isBalanced(TreeNode root){
        if(root == null){
            return true;
        }

        int leftHeight = MaxDepth(root.left);
        int rightHeight = MaxDepth(root.right);

        return Math.abs(leftHeight - rightHeight) <= 1
                && isBalanced(root.left)
                && isBalanced(root.right);
    }

    public int MaxDepth(TreeNode root){
        if(root == null){
            return 0;
        }

        int leftH = MaxDepth(root.left);
        int rightH = MaxDepth(root.right);

        return Math.max(leftH,rightH)+1;
    }
}
public class Test {
    public static void main(String[] args) {
        Solution solution = new Solution();

        TreeNode root = new TreeNode(3,new TreeNode(9),new TreeNode(20));
        root.right.left = new TreeNode(15);
        root.right.right = new TreeNode(7);

        System.out.println(solution.isBalanced(root));
    }
}

1.5. 对称二叉树

      要判断二叉树是否是对称的,也就是判断左右子树是否是对称的(如下图所示)。root.left与root.right是否是对称的,再判断下面的子结点是否对称,也就是递归的条件。

class TreeNode{
    public int val;
    public TreeNode left;
    public TreeNode right;

    public TreeNode(){}

    public TreeNode(int val) {
        this.val = val;
    }

    public TreeNode(int val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

public class Solution {
    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(leftTree == null && rightTree == null){
            return true;
        }

        if(leftTree.val != rightTree.val){
            return false;
        }

        return isSymmetricChild(leftTree.left,rightTree.right)
                && isSymmetricChild(leftTree.right,rightTree.left);
    }
}
public class Test {
    public static void main(String[] args) {
        Solution solution = new Solution();
        TreeNode root = new TreeNode(1,new TreeNode(2),new TreeNode(2));

        root.left.left = new TreeNode(3);
        root.left.right = new TreeNode(4);
        root.right.left = new TreeNode(4);
        root.right.right = new TreeNode(3);

        System.out.println(solution.isSymmetric(root));
    }
}

相关文章:

  • QILSTE H6-C111LB高亮蓝光LED灯珠 发光二极管LED
  • Feign 类型转换问题解析:如何正确处理 `ResponseEntity<byte[]>` 返回值
  • keil中出现Error_Handler错误的解决方法
  • 【学习笔记】计算机网络(四)
  • bug exposed beyond app through Intent.getData()
  • 从哪里下载WinPrefetchView最安全?
  • [Ubuntu] 记录系统崩掉进入initramfs模式后的解决方法
  • Linux:进程信号(二.信号的保存与处理、递达、volatile关键字、SIGCHLD信号)
  • Mind 爱好者周刊 第13期 | 人类神经重放和尖波涟漪综述、饥饿对记忆巩固的影响、使用AI从大脑中解码语言、B族维生素与神经精神疾病的关系……
  • 【生成模型】【ComfyUI(三)】使用WebAPI批量调用ComfyUI
  • Linux发展史、发行版本、特性以及应用场景
  • Revisiting Reverse Distillation for Anomaly Detection
  • 在CentOS7上部署与关闭Flask接口
  • 视频孪生技术赋能文旅数字化转型:重构景区体验与管理新模式
  • 嵌入式开发:傅里叶变换(5):STM32和Matlab联调验证FFT
  • MobSF(Mobile Security Framework) 的详细介绍、安装指南、配置说明
  • 物联网平台建设方案一
  • 力扣提升第一天
  • 在linux中利用conda安装blast
  • openssh9.9p2部分Linux操作系统的rpm包
  • 沧州市建设服务中心网站/日本进口yamawa
  • 太原优化型网站建设/百度seo网络营销书
  • 如何做网页游戏网站/企业策划
  • 在工商局网站怎么做清算/常州网站制作维护
  • wordpress快讯插件/网站页面优化包括
  • 做网站建设与推广企业/天津seo排名收费