【每日一题】剑指offer.26 树的子结构

763 阅读3分钟

首先,这是一道中等难度的题,我觉得这道题难度还可以(这里不是说我很牛,而是很久没有练习算法的我遇到这道题觉得特别有意思,感觉找到了一些做题的感觉,从这里开始,我会一步一步的深入学习递归以及二叉树问题),现在的我在算法方面和新手没有什么区别,相对于以前刷的简单题,我觉得这才是能让我写了之后印象深刻的题目!

题目:

输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)

B是A的子结构, 即 A中有出现和B相同的结构和节点值。

例如: 给定的树 A:

     3     /
4   5   /
1   2 给定的树 B:

   4    /  1 返回 true,因为 B 与 A 的一个子树拥有相同的结构和节点值。

示例 1:

输入:A = [1,2,3], B = [3,1] 输出:false 示例 2:

输入:A = [3,4,5,1,2], B = [4,1] 输出:true 限制:

0 <= 节点个数 <= 10000

第一思路(不一定对):

首先想到模式匹配可以解决子结构问题,然后字符串的contains函数;我采用了字符串,运用先序遍历,遍历出所有的节点的值(如果左右节点为null则视为-1),这样得出来的就是一个字符串,然后用contains函数即可。 这里,我没能得出结果,中间出了空指针问题,大家可以帮我看一看

List<Integer> list = new ArrayList<>();
public boolean isSubStructure(TreeNode A, TreeNode B) {
   pre(A);
   String A = list.toString();
   list.clear();
   pre(B);
   String B = list.toString();
   return A.contains(B)?true:false;
}

public void pre(TreeNode node) {
    if(node == null) {
        list.add(-1);
    }
    list.add(node.val);
    pre(node.left);
    pre(node.right);
}

题解:

运用递归的思想:我们要匹配子结构,那么只要A中任意一个子节点为根节点开始的子结构和B匹配上即成功。那么我们就遍历整个A,让A的每个节点都和B去做匹配。出现一个即可。从一个节点开始的子结构去和B做递归匹配了。如何递归?当然是两个结构左边和左边,右边和右边比;

 //A中的某个节点为根节点去和B匹配
 public boolean isSubStructure(TreeNode A, TreeNode B) {
    if(A== null || B == null) {
        return false;  //题目有说明,空树不为任何树的子结构
    }
    return iscontail(A,B) || isSubStructure(A.left,B) || isSubStructure(A.right,B); //先判断A的根节点开始的子结构是否包含B结构,如果为false,就会进入递归判断左边,左边全没有就会判断右边。
}
//和B进行匹配
public boolean iscontail(TreeNode A,TreeNode B) {
    if(B == null) { //这里不要诧异,第一次进来肯定不会触发(前面已经过滤),因为这是给后面递归设定的,递归后如果B的子节点中出现了空,那么和b相比的前面结构肯定匹配上了,这个为空说明匹配结束。
        return true;
    }
    if(A == null || A.val != B.val) {
        return false; //出现一个不相等的值就说明结构不同的
    }
    return iscontail(A.left,B.left) && iscontail(A.right,B.right); //前面的操作说明了根节点相同了,想在递归进行左右子节点比较,左右都相等才返回true
}