树的子结构 、子树
自己通过的牛客网的代码
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public boolean HasSubtree(TreeNode root1,TreeNode root2) {
if(root1 == null || root2 == null){
return false;
}
if (root1 == root2) {
return true;
}
boolean result = false;
if(root1.val == root2.val){
result = isSame(root1,root2);
}
if (result) {
return true;
}
return HasSubtree(root1.left,root2) || HasSubtree(root1.right,root2);
}
public boolean isSame(TreeNode root1,TreeNode root2){
if(root1 == root2){
return true;
}
if(root2 == null){
return true;
}
if(root1 == null){
return false;
}
if (root1.val == root2.val) {
return isSame(root1.left,root2.left) && isSame(root1.right,root2.right);
}
return false;
}
}
题目
输入两颗二叉树A,B,判断B是不是A的子结构。(PS:我们约定空树不是任意一个树的子结构)。
思路
要查找树A中是否存在和树B结构一样的子树,我们可以分为两步:第一步在树A中找到和B的根结点的值一样的结点R,第二步再判断树A中以R为根节点的子树是不是包含和树B一样的结构。
这里使用递归的方法即可。
代码
/**
* 输入两棵二叉树A和B,判断B是不是A的子结构。
* 该方法是在A树中找到一个与B树的根节点相等的元素的结点,
* 从这个相等的结点开始判断树B是不是树A的子结构,如果找到其的一个就返回,
* 否则直到所有的结点都找完为止。
*
* @param root1 树A的根结点
* @param root2 树B的根结点
* @return true:树B是树A的子结构,false:树B是不树A的子结构
*/
public static boolean hasSubtree(TreeNode root1, TreeNode root2) {
// 只要两个对象是同一个就返回true
// 【注意此处与书本上的不同,书本上的没有这一步】
if (root1 == root2) {
return true;
}
// 只要树B的根结点点为空就返回true
if (root2 == null) {
return true;
}
// 树B的根结点不为空,如果树A的根结点为空就返回false
if (root1 == null) {
return false;
}
// 记录匹配结果
boolean result = false;
// 如果结点的值相等就,调用匹配方法
if (root1.value == root2.value) {
result = match(root1, root2);
}
// 如果匹配就直接返回结果
if (result) {
return true;
}
// 如果不匹配就找树A的左子结点和右子结点进行判断
return hasSubtree(root1.left, root2) || hasSubtree(root1.right, root2);
}
/**
* 从树A根结点root1和树B根结点root2开始,一个一个元素进行判断,判断B是不是A的子结构
*
* @param root1 树A开始匹配的根结点
* @param root2 树B开始匹配的根结点
* @return 树B是树A的子结构,false:树B是不树A的子结构
*/
public static boolean match(TreeNode root1, TreeNode root2) {
// 只要两个对象是同一个就返回true
if (root1 == root2) {
return true;
}
// 只要树B的根结点点为空就返回true
if (root2 == null) {
return true;
}
// 树B的根结点不为空,如果树A的根结点为空就返回false
if (root1 == null) {
return false;
}
// 如果两个结点的值相等,则分别判断其左子结点和右子结点
if (root1.value == root2.value) {
return match(root1.left, root2.left) && match(root1.right, root2.right);
}
// 结点值不相等返回false
return false;
}
public class Solution {
//先从根开始再把左作为根,再把右作为根由本函数决定。把一个为根的时候的具体比对过程是第二个函数决定。
//从根可以认为是一颗树,从左子树开始又可以认为是另外一颗树,从右子树开始又是另外一棵树。
//本函数就是判断这一整颗树包不包含树2,如果从根开始的不包含,就从左子树作为根节点开始判断,
//再不包含从右子树作为根节点开始判断。
//是整体算法递归流程控制。
public boolean HasSubtree(TreeNode root1,TreeNode root2) {
boolean res = false;
if (root1 != null && root2 != null) {
if(root1.value == root2.value){
res = doesTree1haveTree2(root1,root2);
}
if(!res)
{
res = HasSubtree(root1.left, root2);
}
if(!res)
{
res = HasSubtree(root1.right, root2);
}
}
return res;
}
//本函数,判断从当前的节点 ,开始两个树能不能对应上,是具体的比对过程
public boolean doesTree1haveTree2(TreeNode root1,TreeNode root2) {
if(root2 == null)
{
return true;
}
if(root1 == null)
{
return false;
}
if(root1.value != root2.value){
return false;
}
//如果根节点可以对应上,那么就去分别比对左子树和右子树是否对应上
return doesTree1haveTree2(root1.left, root2.left) && doesTree1haveTree2(root1.right, root2.right);
}
子树
LeetCode
以上代码1在LeetCode中不通过 (因为上面是子结构) LeetCode是子树
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isSubtree(TreeNode root1, TreeNode root2) {
// 只要两个对象是同一个就返回true
// 【注意此处与书本上的不同,书本上的没有这一步】
if (root1 == root2) {
return true;
}
// 只要树B的根结点点为空就返回true
if (root2 == null) {
return true;
}
// 树B的根结点不为空,如果树A的根结点为空就返回false
if (root1 == null) {
return false;
}
// 记录匹配结果
boolean result = false;
// 如果结点的值相等就,调用匹配方法
if (root1.val == root2.val) {
result = match(root1, root2);
}
// 如果匹配就直接返回结果
if (result) {
return true;
}
// 如果不匹配就找树A的左子结点和右子结点进行判断
return isSubtree(root1.left, root2) || isSubtree(root1.right, root2);
}
public boolean match(TreeNode root1, TreeNode root2) {
// 只要两个对象是同一个就返回true
if (root1 == root2) {
return true;
}
if(root2 == null && root1 == null){
return true;
}
if (root1 == null || root2== null) {
return false;
}
// 如果两个结点的值相等,则分别判断其左子结点和右子结点
if (root1.val == root2.val) {
return match(root1.left, root2.left) && match(root1.right, root2.right);
}
// 结点值不相等返回false
return false;
}
}
其实两个题的区别就是
if(root2 == null){
return true;
}
if(root1 == null){
return false;
}
if(root1 == null && root2 == null){
return true;
}
if (root2 == null && root1 != null) {
return false;
}
if (root2 != null && root1 == null) {
return false;
}