首页 > 试题广场 >

判断t1树中是否有与t2树拓扑结构完全相同的子树

[编程题]判断t1树中是否有与t2树拓扑结构完全相同的子树
  • 热度指数:1862 时间限制:C/C++ 3秒,其他语言6秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
给定彼此独立的两棵二叉树,判断 t1 树是否有与 t2 树拓扑结构完全相同的子树。
设 t1 树的边集为 E1,t2 树的边集为 E2,若 E2 等于 E1 ,则表示 t1 树和t2 树的拓扑结构完全相同。

输入描述:
第一行输入两个整数 n 和 root,n 表示二叉树 t1 的总节点个数,root 表示二叉树 t1 的根节点。
以下 n 行每行三个整数 fa,lch,rch,表示 fa 的左儿子为 lch,右儿子为 rch。(如果 lch 为 0 则表示 fa 没有左儿子,rch同理)
第 n+2 行输入两个整数 m 和 root,n 表示二叉树 t2 的总节点个数,root 表示二叉树 t2 的根节点。
以下 m 行每行三个整数 fa,lch,rch,表示 fa 的左儿子为 lch,右儿子为 rch。(如果 lch 为 0 则表示 fa 没有左儿子,rch同理)


输出描述:
如果 t1 树有与 t2 树拓扑结构完全相同的子树,则输出 "true",否则输出 "false"。
示例1

输入

9 1
1 2 3
2 4 5
4 0 8
8 0 0
5 9 0
9 0 0
3 6 7
6 0 0
7 0 0
5 2
2 4 5
4 0 8
8 0 0
5 9 0
9 0 0

输出

true

备注:

这个题目非常经典,有如下三个可能性:
  1. A和B两棵树完全一样;
  2. B树为A树的左子树;
  3. B树为A树的右子树。
然后递归求解,挨个检查两棵树的节点值是否相等。(1) 如果B树没有结点了,说明所有节点都检查完了还没发现不相等的情况,找到了B树在A树中的子结构;(2) 如果A树没有节点了,说明A树剩下的子树部分规模比B树小,不可能再存在B树的结构;(3) A树和B树的节点值不相等也说明结构不符合。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.HashMap;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        // 构建树A
        String[] params = br.readLine().split(" ");
        int n = Integer.parseInt(params[0]);
        TreeNode treeA = new TreeNode(Integer.parseInt(params[1]));
        HashMap<Integer, TreeNode> map = new HashMap<>();
        map.put(treeA.val, treeA);
        for(int i = 0; i < n; i++){
            params = br.readLine().split(" ");
            int val = Integer.parseInt(params[0]);
            int leftVal = Integer.parseInt(params[1]);
            int rightVal = Integer.parseInt(params[2]);
            TreeNode node = map.get(val);
            if(leftVal != 0) {
                node.left = new TreeNode(leftVal);
                map.put(leftVal, node.left);
            }
            if(rightVal != 0) {
                node.right = new TreeNode(rightVal);
                map.put(rightVal, node.right);
            }
        }
        // 构建树B
        params = br.readLine().split(" ");
        int m = Integer.parseInt(params[0]);
        TreeNode treeB = new TreeNode(Integer.parseInt(params[1]));
        map.clear();
        map.put(treeB.val, treeB);
        for(int i = 0; i < m; i++){
            params = br.readLine().split(" ");
            int val = Integer.parseInt(params[0]);
            int leftVal = Integer.parseInt(params[1]);
            int rightVal = Integer.parseInt(params[2]);
            TreeNode node = map.get(val);
            if(leftVal != 0) {
                node.left = new TreeNode(leftVal);
                map.put(leftVal, node.left);
            }
            if(rightVal != 0) {
                node.right = new TreeNode(rightVal);
                map.put(rightVal, node.right);
            }
        }
        System.out.println(isSubStructure(treeA, treeB));
    }
    
    private static boolean isSubStructure(TreeNode treeA, TreeNode treeB) {
        if(treeA == null || treeB == null) return false;    // 空树不是任何一棵树的子树
        // 树A和树B完全一样,或树B为树A的左右子树之一都可以
        return isSame(treeA, treeB) || isSubStructure(treeA.left, treeB) || isSubStructure(treeA.right, treeB);
    }
    
    private static boolean isSame(TreeNode treeA, TreeNode treeB) {
        if(treeB == null) return true;     // B树到空,说明节点都检查完了,返回true
        if(treeA == null || treeA.val != treeB.val) return false;    // A树为空或节点值不同,返回false
        // 检查两棵树的左右子树是否都相同
        return isSame(treeA.left, treeB.left) && isSame(treeA.right, treeB.right);
    }
}

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

发表于 2021-12-04 09:32:12 回复(0)