代码随想录:二叉树6-8

目录

226.翻转二叉树

代码(前序递归)

代码(后序递归)

代码(前序迭代)

代码(层序迭代)

101.对称二叉树

100.相同的树

572.另一棵树的子树


226.翻转二叉树

题目

给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。

示例 1:

输入:root = [4,2,7,1,3,6,9]
输出:[4,7,2,9,6,3,1]

代码(前序递归)

class Solution {
    public TreeNode invertTree(TreeNode root) {
        preOrder(root);
        return root;


    }
    //前序递归,一边遍历一边反转左右孩子指针
    public void preOrder(TreeNode root){
        //终止条件
        if(root == null){
            return;
        }
        //单层逻辑
        swap(root); //遍历到该节点就翻转左右指针
        preOrder(root.left); //遍历左子树
        preOrder(root.right);  //遍历右子树
    }

    //翻转左右孩子的指针
    public void swap(TreeNode root){
        TreeNode tmp = new TreeNode();
        tmp = root.left;
        root.left = root.right;
        root.right = tmp;
    }
}

代码(后序递归)

/**
 * Definition for a binary tree node.
 * public 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;
 *     }
 * }
 */
class Solution {
    public TreeNode invertTree(TreeNode root) {
        postOrder(root);
        return root;


    }
    //后序递归,一边遍历一边反转左右孩子指针
    public void postOrder(TreeNode root){
        //终止条件
        if(root == null){
            return;
        }
        //单层逻辑
        postOrder(root.left); //遍历左子树(左)
        postOrder(root.right);  //遍历右子树(右)
        swap(root); //遍历到该节点就翻转左右指针(中)
    }

    //翻转左右孩子的指针
    public void swap(TreeNode root){
        TreeNode tmp = new TreeNode();
        tmp = root.left;
        root.left = root.right;
        root.right = tmp;
    }
}

代码(前序迭代)

class Solution {
    public TreeNode invertTree(TreeNode root) {

        //前序迭代遍历+遍历时翻转左右孩子指针
        Stack<TreeNode> stack = new Stack<>();

        if(root == null){
            return root;
        }

        stack.push(root);  //根节点入栈

        while(!stack.isEmpty()){
            TreeNode cur = stack.pop(); //出栈==遍历节点
            swap(cur); //交换左右孩子指针
            if(cur.right != null){
                stack.push(cur.right);
            }
            if(cur.left != null){
                stack.push(cur.left);
            }
        }
        return root;
    }
    
    //翻转左右孩子的指针
    public void swap(TreeNode root){
        TreeNode tmp = new TreeNode();
        tmp = root.left;
        root.left = root.right;
        root.right = tmp;
    }
}

代码(层序迭代)

class Solution {
    public TreeNode invertTree(TreeNode root) {

        //层序迭代遍历+遍历时翻转左右孩子指针
        Queue<TreeNode> que = new ArrayDeque<>();

        if(root == null){
            return root;
        }
        que.offer(root); //根节点入队

        while(!que.isEmpty()){
            int size = que.size();
            while(size-- > 0){
                TreeNode cur = que.poll(); //出队==遍历
                swap(cur);  //交换左右孩子指针,要先交换再把孩子加到队列里
                if(cur.left != null){
                    que.offer(cur.left);
                }
                if(cur.right != null){
                    que.offer(cur.right);
                }
            }
        }
        return root;
    }
    
    //翻转左右孩子的指针
    public void swap(TreeNode root){
        TreeNode tmp = new TreeNode();
        tmp = root.left;
        root.left = root.right;
        root.right = tmp;
    }
}

总结

        翻转二叉树可以用前序、后序、层序遍历,一边遍历时一边翻转当前遍历节点的左右指针即可。对比单纯的遍历二叉树,就是把遍历节点值add到result的操作,修改为swap(cur)即可。所以只要熟练二叉树的递归和迭代遍历,加上想清楚这道题在遍历时增加什么操作即可。核心算法还是二叉树的遍历。

101.对称二叉树

题目

给你一个二叉树的根节点 root , 检查它是否轴对称。

示例 1:

输入:root = [1,2,2,3,4,4,3]
输出:true

代码

/**
 * Definition for a binary tree node.
 * public 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;
 *     }
 * }
 */
class Solution {
    public boolean isSymmetric(TreeNode root) {
        return compare(root.left,root.right);

    }
    //比较左右子树是否相互翻转(后序,左右中+右左中)
    public boolean compare(TreeNode left,TreeNode right){
        //终止条件(left和right这一层先比较)
        if(left == null && right != null){
            return false; //左空右不空
        }
        else if(left != null && right == null){
            return false; //左不空右空
        }
        else if(left == null && right == null){
            return true; //左右都为空
        }
        //这里的左右节点都不会为空了,可以获取val
        else if(left.val != right.val){
            return false;  //不为空,但是左右节点值不同
        }

        //当面的终止条件,如果没终止,说明left和right的值一样,要继续往下一层遍历
        //单层逻辑,对于左子树遍历左右中,对于右子树,遍历右左中
        boolean outside = compare(left.left,right.right); //比较外侧节点
        boolean inside = compare(left.right,right.left); //比较内侧节点
        return outside&&inside;
    }
}

100.相同的树

题目

给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。

如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

示例 1:

输入:p = [1,2,3], q = [1,2,3]
输出:true

代码

class Solution {
    public boolean isSameTree(TreeNode p, TreeNode q) {
        boolean result = compare(p,q);
        return result;
    }
    public boolean compare(TreeNode p,TreeNode q){
        //终止条件
        if(p != null && q == null){
            return false;  //左不空右空
        }
        else if(p == null && q != null){
            return false;  //左空右不空
        }
        else if(p == null && q == null){
            return true;  //左右都空
        }
        else if(p.val != q.val){
            return false;  //左右都不空但是节点值不一样
        }
        //如果上面终止条件都不满足,没有return,说明左右的节点值一样,要继续往后面判断
        //单层逻辑,后序遍历左右中
        boolean left = compare(p.left,q.left);  //比较左边
        boolean right = compare(p.right,q.right);  //比较右边
        return left && right;
    }
}

572.另一棵树的子树

题目

给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false 。

二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树。

示例 1:

输入:root = [3,4,5,1,2], subRoot = [4,1,2]
输出:true

代码(前序迭代)

/**
 * Definition for a binary tree node.
 * public 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;
 *     }
 * }
 */
class Solution {
    public boolean isSubtree(TreeNode root, TreeNode subRoot) {
        Stack<TreeNode> stack = new Stack<>();
        if(subRoot == null){
            return true;
        }

        //核心逻辑是,前序遍历root,不断判断是否和subroot树相同
        stack.push(root); //根节点入栈
        boolean result = fase;  //初始reslut
        //result == false,是只要compare返回true,说明存在包含关系,就可以不用继续判断了
        while(!stack.isEmpty() && result == false){
            TreeNode cur = stack.pop();
            //比较cur和subroot树是否相同,如果返回true直接结束循环
            result = compare(cur,subRoot);
            //如果不相同,继续前序遍历
            if(cur.right != null){
                stack.push(cur.right);  //右子树进栈
            }
            if(cur.left != null){
                stack.push(cur.left);  //左子树进栈
            }
        }
        return result;
    }

    //compare用于判断两个数是否相同
    public boolean compare(TreeNode p,TreeNode q){
        //终止条件
        if(p != null && q == null){
            return false;  //左不空右空
        }
        else if(p == null && q != null){
            return false;  //左空右不空
        }
        else if(p == null && q == null){
            return true;  //左右都空
        }
        else if(p.val != q.val){
            return false;  //左右都不空但是节点值不一样
        }
        //如果上面终止条件都不满足,没有return,说明左右的节点值一样,要继续往后面判断
        //单层逻辑,后序遍历左右中
        boolean left = compare(p.left,q.left);  //比较左边
        boolean right = compare(p.right,q.right);  //比较右边
        return left && right;
    }
}

 代码(层序迭代)

class Solution {
    public boolean isSubtree(TreeNode root, TreeNode subRoot) {
        Queue<TreeNode> que = new ArrayDeque<>();

        que.offer(root);

        while(!que.isEmpty()){
            int len = que.size();
            while(len-- > 0){
                TreeNode cur = que.poll();
                boolean res = compare(cur,subRoot);
                if(res == true){
                    return true;
                }
                if(cur.left != null){
                    que.offer(cur.left);
                }
                if(cur.right != null){
                    que.offer(cur.right);
                }
            }
        }
        return false;
    }

    //compare用于判断两个数是否相同
    public boolean compare(TreeNode p,TreeNode q){
        //终止条件
        if(p != null && q == null){
            return false;  //左不空右空
        }
        else if(p == null && q != null){
            return false;  //左空右不空
        }
        else if(p == null && q == null){
            return true;  //左右都空
        }
        else if(p.val != q.val){
            return false;  //左右都不空但是节点值不一样
        }
        //如果上面终止条件都不满足,没有return,说明左右的节点值一样,要继续往后面判断
        //单层逻辑,后序遍历左右中
        boolean left = compare(p.left,q.left);  //比较左边
        boolean right = compare(p.right,q.right);  //比较右边
        return left && right;
    }
}

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

守岁白驹hh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值