zoukankan      html  css  js  c++  java
  • 26 树的子结构(第3章 高质量的代码-代码的鲁棒性)

    题目描述:

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

    测试用例:  

     功能测试(树AB都是普通的二叉树;树B是或不是树A的子结构)

    特殊输入测试(两颗树的一个或两个的根节点为nullptr;二叉树的所有节点都没有左子树或者右子树

    解题思路:

    1)使用递归调用

    分成两步:第一步,在树A中找到与树B的根节点值一样的节点R(实质上是树的遍历);第二步,判断树A中以R为跟节点的子树是不是包含和树B一样的结构(终止条件是到达树A(不含树B结构)或树B的叶节点(含有树B结构)) 

    /*
    struct TreeNode {
    	int val;
    	struct TreeNode *left;
    	struct TreeNode *right;
    	TreeNode(int x) :
    			val(x), left(NULL), right(NULL) {
    	}
    };*/
    class Solution {
    public:
        bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
        {
            bool result = false;
            if(pRoot1!=nullptr && pRoot2!=nullptr){
                if(pRoot1->val == pRoot2->val)
                    //两个树的根节点相等,判断子树是否相等
                    result = DoesTree1HaveTree2(pRoot1,pRoot2);
                if(!result)
                    //在左子树中查找
                    result = HasSubtree( pRoot1->left,  pRoot2);
                if(!result)
                    //在右子树中查找
                    result = HasSubtree( pRoot1->right,  pRoot2);
            }
            
            return result;
        }
        
        bool DoesTree1HaveTree2(TreeNode* pRoot1, TreeNode* pRoot2){
            //根节点相等才会进入到该函数
            //给出终止条件
            if(pRoot2==nullptr)
                return true;
            if(pRoot1==nullptr)
                return false;
            
            if(pRoot1->val != pRoot2->val)
                return false;
            //左右子树都相等,返回true
            return DoesTree1HaveTree2(pRoot1->left,pRoot2->left) && DoesTree1HaveTree2(pRoot1->right,pRoot2->right);
        }
    };  

    编程时注意对nullptr的判断,以防代码报错。

    2)利用好短路特性,完全不用那么多flag

    class Solution {
        bool isSubtree(TreeNode* pRootA, TreeNode* pRootB) {
            if (pRootB == NULL) return true;
            if (pRootA == NULL) return false;
            if (pRootB->val == pRootA->val) {
                return isSubtree(pRootA->left, pRootB->left)
                    && isSubtree(pRootA->right, pRootB->right);
            } else return false;
        }
    public:
        bool HasSubtree(TreeNode* pRootA, TreeNode* pRootB)
        {
            if (pRootA == NULL || pRootB == NULL) return false;
            return isSubtree(pRootA, pRootB) ||
                HasSubtree(pRootA->left, pRootB) ||
                HasSubtree(pRootA->right, pRootB);
        }
    };
    

    3)  KMP

    左边数先序遍历是:1 2 4 5 3,右边是:1 2 3

    子树和子结构是两码事,子树的意思是给定一个节点就要遍历到它的所有叶节点为止,而子结构不需要,可以中途停止。子树能用序列化+KMP,子结构不能,因为子结构不管采用何种方式序列化,都不能保证在整棵树的序列化中连续

    可以用KMP吧?都先序遍历,如果后者是前者的子结构,则后者的先序遍历序列一定是前者的先序遍历的子串(注意是子串,不是子序列),反之,如果不是子结构,B的固定先序有多种结构,但是一定不是前者的子串了。

    学习KMP算法,怎样寻找子串

    4)将树进行序列化的时候,空结点要用#号或其他符号填充,这样可以保证这个序列能唯一的表示一棵树,如后面有一个题目《树的序列化和反序列化》也是这样做的。

    基础知识:

    1)深度优先遍历(DFS)Depth First Search 

    和树的先序遍历比较类似。

    2)广度优先搜索算法(Breadth First Search),又称为"宽度优先搜索"或"横向优先搜索",简称BFS。

    https://www.cnblogs.com/skywang12345/p/3711483.html 

    3)KMP算法要解决的问题就是在字符串(也叫主串)中的模式(pattern)定位问题。说简单点就是我们平时常说的关键字搜索。模式串就是关键字(接下来称它为P),如果它在一个主串(接下来称为T)中出现,就返回它的具体位置,否则返回-1(常用手段)。

    4)kmp时间复杂度是O(n + m), 递归查找O(n * m)

    5)一种遍历可能有多种树,两种遍历才能确定一个树,

  • 相关阅读:
    信息系统项目管理师2020年下半年下午案例分析题及答案
    信息系统项目管理师2019年下半年下午案例分析题及答案
    系统集成项目管理工程师2021年上半年下午案例分析题及答案
    信息系统项目管理师2021年下半年下午案例分析题及答案
    信息系统项目管理师2019年上半年下午案例分析题及答案
    系统集成项目管理工程师2021年下半年下午案例分析题及答案
    信息系统项目管理师2021年上半年下午案例分析题及答案
    深入理解C#笔记(1)
    SqlBulkCopy批量插入数据
    SQL ROW_NUMBER() OVER函数的基本用法用法
  • 原文地址:https://www.cnblogs.com/GuoXinxin/p/10449529.html
Copyright © 2011-2022 走看看