剑指 Offer 26. 树的子结构

185 阅读2分钟

题目描述

image.png

  • 双递归
  • 递归判断两棵树是否有相同的节点,遇到值相同的节点后,再递归判断是不是子结构。
class Solution {
    public boolean isSubStructure(TreeNode A, TreeNode B) {
        if (A == null || B == null) {
            return false;
        }
        // 如果节点当前ab节点值不一样,还需要向下判断,所以这么写,详见lc572
        if (A.val == B.val && dfs(A, B)) {
            return true;
        } else {
            return isSubStructure(A.left, B) || isSubStructure(A.right, B);
        }
    }

    public boolean dfs(TreeNode A, TreeNode B) {
        if (A == null && B == null) { //到叶子结点结构都一样
            return true;
        }
        if (A == null) { // b中的节点a中没有
            return false;
        }
        if (B == null) { // b走完了,a中的节点b中没有
            return true;
        }
        if (A.val == B.val) {// 继续向下判断
            return dfs(A.left, B.left) && dfs(A.right, B.right);
        } else {
            return false; // 节点值不相同,直接false
        }
        
    }
}

思路

  • 递归判断两棵树是否有相同的节点,遇到值相同的节点后,再递归判断是不是子结构。
  • 递归判断是不是子结构的思路,维护两个boolean,left right
    • A.val != B.val 必然不是
    • A.left不空,B.left不空,往下递归
    • A.left空 B.left不空,不可能是子结构
    • A.left不空 B.left空
    • A.left空 B.left空
    • right同理

365ED0A523699E43326AE3D6842E41C2.png

代码

class Solution {
    public boolean isSubStructure(TreeNode A, TreeNode B) {
        if (A == null || B == null) {//终止条件A==null,B==null是为了处理B为空树
            return false;
        }
        if (A.val == B.val && isSame(A, B)) {//找到了节点值相同,并且是子结构
            return true;
        } else {
            return isSubStructure(A.left, B) || isSubStructure(A.right, B);//还得继续往下找,节点值相同但不是子结构也不行
        }
    }
    //判断node2是不是node1的子结构
    public boolean isSame(TreeNode node1, TreeNode node2) {
        boolean left = false;
        boolean right = false;
        if (node1.val != node2.val) {//【A】
            return false;
        } else {
            if (node1.left != null && node2.left != null) {//【B】左子节点均不空,向下递归判断
                left = isSame(node1.left, node2.left);
            } else if (node1.left == null && node2.left != null) {//【C】原树左子节点空了,小树左子节点不空,必不是子结构
                return false;
            } else {//【D,E】小树树左子节点空了,原树不空;或者两棵树都遇到空节点了
                left = true;
            }

            if (node1.right != null && node2.right != null) {//右子节点均不空,递归
                right = isSame(node1.right, node2.right);
            } else if (node1.right == null && node2.right != null) {
                return false;
            } else {
                right = true;
            }
        }
        return left && right;//左右都true才行
    }
}