树的题目,一般用递归来写
双重递归
class Solution {
public:
bool isSubtree(TreeNode* p1, TreeNode* p2) {
if (p2 == nullptr) return true; // 树 B 已匹配完
if (p1 == nullptr) return false; // 树 A 已空但树 B 未空
if (p1->val != p2->val) return false;
return isSubtree(p1->left, p2->left) && isSubtree(p1->right, p2->right);
}
bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2) {
if (pRoot1 == nullptr || pRoot2 == nullptr) return false;
// 当前节点匹配且子树匹配,或左/右子树中匹配
return (pRoot1->val == pRoot2->val && isSubtree(pRoot1, pRoot2)) ||
HasSubtree(pRoot1->left, pRoot2) ||
w HasSubtree(pRoot1->right, pRoot2);
}
};
也可以用层次遍历+递归来写:层次遍历找到某个节点和p2的根值相同,然后递归判断是否匹配。
class Solution {
public:
//层次遍历判断两个树是否相同
bool helper(TreeNode* p1, TreeNode* p2) {
if (p2 == nullptr) return true; // 树 B 已匹配完
if (p1 == nullptr) return false; // 树 A 已空但树 B 未空
if (p1->val != p2->val) return false;
return helper(p1->left, p2->left) && helper(p1->right, p2->right);
}
bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2) {
if (pRoot1 == nullptr || pRoot2 == nullptr)
return false;
queue<TreeNode*> q;
q.push(pRoot1);
while (!q.empty()) {
TreeNode* node = q.front();
q.pop();
if (node->val == pRoot2->val) {
if (helper(node, pRoot2))
return true;
}
if (node->left)
q.push(node->left);
if (node->right)
q.push(node->right);
}
return false;
}
};
还有双重层次遍历的做法,本质上是递归的层次遍历版本:
- step 1:先判断空树,空树不为子结构。
- step 2:利用队列辅助,层次遍历第一棵树,每次检查遍历到的节点是否和第二棵树的根节点相同。
- step 3:若是相同,可以以该节点为子树根节点,再次借助队列辅助,同步层次遍历这个子树与第二棵树,这个时候以第二棵树为基,只要找到第二棵树的全部节点,就算找到了子结构。
class Solution {
public:
//层次遍历判断两个树是否相同
bool helper(TreeNode* root1, TreeNode* root2){
queue<TreeNode*> q1, q2;
q1.push(root1);
q2.push(root2);
//以树2为基础,树1跟随就可以了
while(!q2.empty()){
TreeNode* node1 = q1.front();
TreeNode* node2 = q2.front();
q1.pop();
q2.pop();
//树1为空或者二者不相等
if(node1 == NULL || node1->val != node2->val)
return false;
//树2还有左子树
if(node2->left){
//子树入队
q1.push(node1->left);
q2.push(node2->left);
}
//树2还有右子树
if(node2->right){
//子树入队
q1.push(node1->right);
q2.push(node2->right);
}
}
return true;
}
bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2) {
if(pRoot1 == NULL || pRoot2 == NULL)
return false;
queue<TreeNode*> q;
q.push(pRoot1);
while(!q.empty()){
TreeNode* node = q.front();
q.pop();
if(node->val == pRoot2->val){
if(helper(node, pRoot2))
return true;
}
if(node->left)
q.push(node->left);
if(node->right)
q.push(node->right);
}
return false;
}
};
二叉树的层次遍历模板
#include <queue>
#include <vector>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> result;
if (!root) return result; // 空树直接返回
queue<TreeNode*> q;
q.push(root);
while (!q.empty()) {
int levelSize = q.size(); // 当前层的节点数
vector<int> currentLevel;
for (int i = 0; i < levelSize; ++i) {
TreeNode* node = q.front();
q.pop();
currentLevel.push_back(node->val);
if (node->left) q.push(node->left);
if (node->right) q.push(node->right);
}
result.push_back(currentLevel); // 保存当前层结果
}
return result;
}