树的子结构
Posted whitebear
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树的子结构相关的知识,希望对你有一定的参考价值。
时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
题目描述
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
知识铺垫:
先来看下子树和子结构的概念
子树:只要包含了一个节点,就得包含这个节点下的所有节点
子结构:包含了一个节点,可以只取左子树或右子树,或者不取,强调结构上的一致
(可参考:https://blog.csdn.net/wushuomin/article/details/79943737)
思路:
一颗大树A,一颗小树B,首先判断A的根节点是否与B的根节点相同,不相同,就依次去A根节点的左子树、右子树上查找,如果存在(假设A中与B的根节点相等的节点为D),此时需要判断的就是D的左子树、右子树是否与B的根节点的左子树、右子树相同节点结构,终止条件:如果B先访问到头了,即小树B先达到NULL,说明B就是A的子结构,如果大树A达到NULL,说明就不是A的子结构。
采用递归的方式
/* 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 != NULL && pRoot2 != NULL) { if(pRoot1->val == pRoot2->val) { //该根节点作为起点判断是否包含pRoot2 result = judgeSubTree(pRoot1,pRoot2); } //如果没有找到,就去该节点的左子树中找 if(!result) { result = HasSubtree(pRoot1->left,pRoot2); } //如果还没有找到,就去该节点的右子树中找 if(!result) { result = HasSubtree(pRoot1->right,pRoot2); } } return result; } private: bool judgeSubTree(TreeNode *node1,TreeNode *node2) { if(node2 == NULL) return true; if(node1 == NULL) return false; if(node1->val != node2->val) { return false; } return judgeSubTree(node1->left,node2->left) && judgeSubTree(node1->right,node2->right); } };
在judgeSubTree函数中对node1->val 与node2->val判断是否相等是有必要的,应为该函数是一个递归函数,下面递归调用的时候,还是要判断传进去的两个节点的值是否相等
另一种写法:
/* 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) { if(pRoot1 == NULL || pRoot2 == NULL) { return false; } return judeSubTree(pRoot1,pRoot2) || judeSubTree(pRoot1->left,pRoot2) ||judeSubTree(pRoot1->right,pRoot2); } bool judeSubTree(TreeNode* node1,TreeNode * node2) { if(node2 == NULL) return true; if(node1 == NULL) return false; if(node1->val != node2->val) return judeSubTree(node1->left,node2) || judeSubTree(node1->right,node2); return judeSubTree(node1->left,node2->left)&& judeSubTree(node1->right,node2->right); } };
子结构包含与子树,子树会要求更加严格,不仅结构相同,节点的值也要相同,只需要对其值判断相等,不能就直接返回false即可
判断是否为子树:
/* 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) { if(pRoot1 == NULL || pRoot2 == NULL) { return false; } return judeSubTree(pRoot1,pRoot2) || judeSubTree(pRoot1->left,pRoot2) ||judeSubTree(pRoot1->right,pRoot2); } bool judeSubTree(TreeNode* node1,TreeNode * node2) { if(node2 == NULL) return true; if(node1 == NULL) return false; if(node1->val != node2->val) return false; return judeSubTree(node1->left,node2->left)&& judeSubTree(node1->right,node2->right); } };
以上是关于树的子结构的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode810. 黑板异或游戏/455. 分发饼干/剑指Offer 53 - I. 在排序数组中查找数字 I/53 - II. 0~n-1中缺失的数字/54. 二叉搜索树的第k大节点(代码片段