二叉树2—对称性递归问题

本文介绍了对称性递归的概念,通过判断子树是否为另一棵树的子结构以及二叉树的镜像问题,展示了如何利用递归解决对称性问题。文章提供了Java代码实现,包括判断子树是否对称、二叉树镜像转换以及检查二叉树是否对称的方法。通过对树结构的左右子树进行递归操作,实现了对称性的判断和转换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        什么是对称性递归?就是对一个对称的数据结构(这里指二叉树)从整体的对称性思考,把大问题分解成子问题进行递归,即不是单独考虑一部分(比如树的左子树),而是同时考虑对称的两部分(左右子树),从而写出对称性的递归代码。

一、判断B是否是A的子树

/**
 * 先序遍历树A中的每个节点nA 函数: isSubStructure(A, B))
 * 判断树 AA 中 以 nA为根节点的子树 是否包含树B。(对应函数 recur(A, B))
 */
public class Num26_B是否是A的子树 {
    private class TreeNode {
      int val;
      TreeNode left;
      TreeNode right;
      TreeNode(int x) { val = x; }
  }
    public boolean isSubStructure(TreeNode A, TreeNode B) {
        if(A==null&&B==null){
            return true;
        }
        if(A==null||B==null){
            return false;
        }
        //recur:A中是否包含B
        return recur(A,B)||isSubStructure(A.left,B)||isSubStructure(A.right,B);
    }
    //方法1(更优)
//    //判断A中是否包含B
//    private boolean recur(TreeNode A, TreeNode B) {
//        if(B==null){
//            //B走到null,B遍历完毕了,说明B一定在A中包含。不包含的话中间值不等时就会直接退出
//            return true;
//        }
//        if(A==null){
//            //走到最后了A还在遍历,说明没有值匹配
//            return false;
//        }
//        if(A.val!=B.val){
//            return false;
//        }
//        //值相等,继续遍历下一个左右子树对应结点
//        return recur(A.left,B.left)&&recur(A.right,B.right);
//    }
    //方法2:判断A和BA.left和B或A.right和B是否相等【判断pq是否相等,相等则true,包含关系】
    public boolean recur(TreeNode p, TreeNode q) {
        if(p==null&&q==null){
            return true;
        }
        if(p!=null&&q==null){//注意这一步,当A没有遍历完但B走到了最后,说明B的值在A中已经连续找到完了,也是包含关系。如[10 12 6 8 3 11][10 12 6 8]
            return true;
        }
        if(p==null){//A走到最后还没有值
            return false;
        }
        if(p.val!=q.val){//两棵树根节点的值不相等
            return false;
        }
        //此时两个根节点值相等,再判断子树是否值相等
        return recur(p.left, q.left) && recur(p.right, q.right);
//        return p.val==q.val&& isSameTree(p.left, q.left) && isSameTree(p.right, q.right);//上面几行的简写

    }
}

二、二叉树镜像问题

1.得到一个二叉树镜像后的二叉树

思路:

1)将二叉树的左子树和右子树部分分别镜像,左子树返回根节点left,右子树返回right,left和right分别是根节点的左右子树;

2)再将镜像后的左右子树整体镜像,根节点的左子树挂在镜像后的右树上,root.right挂在left上(root.left=right;root.right=left)

/**
 * 从根节点开始,递归地对树进行遍历,并从叶子节点先开始翻转得到镜像。
 * 如果当前遍历到的节点 root 的左右两棵子树都已经翻转得到镜像,那么我们只需要交换两棵子树的位置
 * 即可得到以root为根节点的整棵子树的镜像
 * 链接:https://leetcode.cn/problems/er-cha-shu-de-jing-xiang-lcof/solution/er-cha-shu-de-jing-xiang-by-leetcode-sol-z44i/
 **/
//输入一个二叉树,输出它的镜像
public class Num27_二叉树的镜像 {
    private class TreeNode {
      int val;
      TreeNode left;
      TreeNode right;
      TreeNode(int x) { val = x; }
    }
    //二叉树的镜像
    public TreeNode mirrorTree(TreeNode root) {
        if(root==null){
            return null;
        }
        //遍历得到左子树和右子树,将左右子树分别镜像。再交换位置整体镜像左右子树
        TreeNode left=mirrorTree(root.left);
        TreeNode right=mirrorTree(root.right);
        //左右子树分别已经镜像好了,把左右再整体镜像:root.left=right;root.right=left
        root.left=right;
        root.right=left;
        return root;
    }
}

2.对称二叉树

思路:对称二叉树左右子树存在镜像关系,只要两棵子树镜像相等,则二叉树对称(只需要判断根节点是否相等,左.left==右.right,左.right==右.left即可)

//请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的
/**
 * 对称二叉树左右子树存在镜像关系,只要两棵子树镜像相等,则对称(只需要判断根节点是否相等,左.left==右.right,左.right==右.left即可)
 */
public class Num28_对称二叉树 {
    public class TreeNode {
      int val;
      TreeNode left;
      TreeNode right;
      TreeNode(int x) { val = x; }
  }
    public boolean isSymmetric(TreeNode root) {
        if(root==null){
            return true;
        }
        return isMirror(root.left,root.right);
    }
    //判断这两个左右子树是否镜像相等
    private boolean isMirror(TreeNode left, TreeNode right) {
        if(left==null&&right==null){
            return true;
        }
        if(left==null||right==null){
            return false;
        }
        if(left.val!=right.val){//左子树根节点和右子树根节点
            return false;
        }
        //结点相等,继续向下遍历判断左子树的左右子树分别与右子树的右左子树是否镜像相等
        return isMirror(left.left,right.right)&&isMirror(left.right,right.left);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值