力扣刷题笔记13—— 树的子结构,递归

树的子结构,递归

问题

来自力扣

输入两棵二叉树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

我的代码


#include <iostream>
using namespace std;
#include <algorithm>
#include <vector>
#include<queue>
#include <typeinfo>
 struct TreeNode {
     int val;
     TreeNode *left;
     TreeNode *right;
     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 };
 
 class Solution {
 public:
	 bool isSubStructure(TreeNode* A, TreeNode* B) {
		 queue <TreeNode> qnode;
		 if (A == NULL || B == NULL) return false;
		 qnode.push(*A);
		 while (!qnode.empty()) {
			 if(issubstructure(qnode.front(), *B)) return true;
			 if (qnode.front().left != NULL)
				 qnode.push(*(qnode.front().left));
			 if (qnode.front().right != NULL)
				 qnode.push(*(qnode.front().right));
			 qnode.pop();

		 }
		 return false;
	 }
	 bool issubstructure(TreeNode A, TreeNode B) {
		 if (B.val == A.val) {
			 if (B.left == NULL || (A.left!= NULL &&issubstructure(*(A.left),*(B.left)))) {
				 if (B.right== NULL || (A.right != NULL && issubstructure(*(A.right), *(B.right)))) {
					 return true;
				 }
			 }
		 }
		 return false;
	 }
 };

int main() {
	TreeNode* root=NULL;
	root = new TreeNode(3);
	root->left = new TreeNode(4);
	root->right = new TreeNode(5);
	root->left->left = new TreeNode(1);
	root->left->right = new TreeNode(2);
	TreeNode* root2 = NULL;
	root2 = new TreeNode(4);
	root2->left = new TreeNode(2);
	TreeNode* root3= NULL;
	Solution mysolution;
	bool s = mysolution.isSubStructure(root3,root2);
	cout << s;
	
	return 0;
}

步骤:

  1. 定义队列qnode
  2. 当A或B是空时,return false。
  3. 当步骤2没return时,将A的头结点压入队列qnode。
  4. 当队列非空时,将队列首元素和B作为参数,调用递归函数issubstructure()。如果返回值是true,则return true。
  5. 当步骤4没return时,检查队列首元素是否有子节点,有则压入队列中,然后pop首元素。
  6. 如果while循环结束了,证明没找到子结构,return false。

递归函数issubstructure():

  1. 先检查值是否相同。
  2. 再检查左分支是否相同(或者B的左分支为NULL)。
  3. 最后检查右分支是否相同(或者B的右分支为NULL)。

示例代码

bool solve(TreeNode *A, TreeNode *B) {
    if (A->val != B->val) {
        return false;
    }
    bool la = (A->left !=  NULL), lb =(B->left != NULL);
    bool ra = (A->right !=  NULL), rb =(B->right != NULL);
    if (la && ra) {
        if (lb && rb) {
            return solve(A->left, B->left) && solve(A->right, B->right);
        } else if (lb) {
            return solve(A->left, B->left);
        } else if (rb) {
            return solve(A->right, B->right);
        } else {
            return true;
        }
    } else if (la) {
        if (lb && rb) {
            return false;
        } else if (lb) {
            return solve(A->left, B->left);
        } else if (rb) {
            return false;
        } else {
            return true;
        }
    } else if (ra) {
        if (lb && rb) {
            return false;
        } else if (lb) {
            return false;
        } else if (rb) {
            return solve(A->right, B->right);
        } else {
            return true;
        }
    } else {
        if (lb == false && rb == false) {
            return true;
        } else {
            return false;
        }
    }
}
bool judge(TreeNode *A, TreeNode *B) {
    queue<TreeNode*> Q;
    Q.push(A);
    bool flag = false;
    while(!Q.empty()) {
        TreeNode *node = Q.front();
        Q.pop();
        if (node->val == B->val) {
            flag = flag || solve(node, B);
        }
        if (node->left) {
            Q.push(node->left);
        }
        if (node->right) {
            Q.push(node->right);
        }
    }
    return flag;
}
class Solution {
public:
    bool isSubStructure(TreeNode* A, TreeNode* B) {
        if (A == NULL || B == NULL) {
            return false;
        }
        return judge(A, B);
    }
};

示例代码也用了队列和递归,且多用了我一个函数,递归函数看着比我复杂,不过本质思路差不多。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小欣CZX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值