剑指Offer 26-27

109 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第17天,点击查看活动详情

26、树的子结构

题目:给定两颗二叉树AB,判断B是不是A的子结构。子结构的定义即A中有出现和B相同结构和节点值。如果存在则返回true。

解题思路

本题只需要事先找到A中和B节点相同值的节点,之后判断此节点的子树是否是树的子结构即可。找到A树中和B树相同的节点即将A树遍历一下,之后判断即可,遍历的方式也有很多,此处采用层序遍历,使用一个栈来保存一棵树的左子树和右子树,之后依次弹出判断,直到树空为止。而判断是否是树的子结构可以使用递归的方式判断,依次判断对应节点是否相等即可,可得代码如下:

public boolean isSubStructure(TreeNode A, TreeNode B) {
    if(B==null) return false;
    Stack<TreeNode> stack = new Stack<>();
    stack.push(A);
    while(!stack.isEmpty()){
        TreeNode cur = stack.pop();
        if(cur.left!=null){
            stack.push(cur.left);
        }
        if(cur.right!=null){
            stack.push(cur.right);
        }
        if(cur.val == B.val){
            if(isSub(cur, B)){
                return true;
            }
        }
    }
    return false;
}

public boolean isSub(TreeNode A, TreeNode B) {
    if(B == null) return true;
    if(A == null || A.val!=B.val) return false;
    boolean left = isSub(A.left, B.left);
    boolean right = isSub(A.right, B.right);
    return left&&right;
}

但此方式时间复杂度为O(n2)O(n^2),较为耗时,最终实际用时5ms

实际上本题较为耗时的地方就在于对树进行遍历,我们可以直接使用递归的方式来遍历整棵树,如下:

public boolean isSubStructure2(TreeNode A, TreeNode B) {
    if(A==null || B==null) return false;
    return isSub(A, B) || isSubStructure2(A.left, B) || isSubStructure2(A.right, B);
}


public boolean isSub(TreeNode A, TreeNode B) {
    if(B == null) return true;
    if(A == null || A.val!=B.val) return false;
    boolean left = isSub(A.left, B.left);
    boolean right = isSub(A.right, B.right);
    return left&&right;
}

此时最终耗时就为0ms

27、二叉树的镜像

题目:完成一个函数,要求输入一颗二叉树输出其二叉树的镜像。

解题思路

还是复习题,通过递归的方式只需要将根节点的左子树赋给根节点的右子树,右子树赋给左子树即可,代码实现也很简单,代码如下:

public TreeNode mirrorTree(TreeNode root) {
    if(root==null) return null;
    TreeNode left = root.left;
    root.left = mirrorTree(root.right);
    root.right = mirrorTree(left);
    return root;
}

时间复杂度为O(n)O(n)