前言
这是七月集训的第十九日,今日的训练内容是 树
解题报告
1.力扣958
原题链接
题目概述
给定一个二叉树的 root ,确定它是否是一个 完全二叉树 。
在一个 完全二叉树 中,除了最后一个关卡外,所有关卡都是完全被填满的,并且最后一个关卡中的所有节点都是尽可能靠左的。它可以包含 1 到 2h 节点之间的最后一级 h 。
解题思路
不得不说,c++的库实在是方便,使用一个辅助队列对树进行层序遍历,如果在队空之前出现了空结点,则说明不是完全二叉树。详见注释。
源码剖析
class Solution {
public:
bool isCompleteTree(TreeNode* root) {
queue<TreeNode*> q; //使用一个辅助队列用于辅助层序遍历
bool reachNull = false;
q.push(root); //首先将根结点入队
while(!q.empty()){
TreeNode* head = q.front(); //记录下队首元素
q.pop(); //队首出队
if(head==nullptr){ //如果队首为空的话就直接结束循环了
reachNull = true; //说明此时遍历到了空结点,且队列非空
continue;
}else{
if(reachNull){ //说明队首出现了空结点
return false;
}
q.push(head->left); //出队结点的左右子树入队
q.push(head->right);
}
}
return true; //如果在队空前没有返回false则说明是完全二叉树
}
};
2.力扣剑指 Offer 26. 树的子结构
原题链接
题目概述
输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)
B是A的子结构, 即 A中有出现和B相同的结构和节点值。
例如:
给定的树 A:3
/ \
4 5
/ \
1 2
给定的树 B:4
/
1
返回 true,因为 B 与 A 的一个子树拥有相同的结构和节点值。
解题思路
分别对树根和子树进行判断,首先找到相同的根结点,然后再对子树进行判断是否成立,详见源码剖析。
源码剖析
class Solution {
public:
bool isSubStructure(TreeNode* A, TreeNode* B) {
if(A == NULL || B == NULL) return false; //递归出口,有一方已经NULL了就不可能匹配了
if(A->val == B->val){
if(detection(A, B))
return true; //首先对可能的子树根结点进行判断,然后再判断子树
}
return isSubStructure(A->left, B) || isSubStructure(A->right, B);//对左右子树递归
}
bool detection(TreeNode* A, TreeNode* B){
if(B == NULL) return true; //只要B的这一侧为NULL则成立
if(A == NULL || A->val != B->val) return false; //只能B为NULL A不可以为NULL
return detection(A->left, B->left) && detection(A->right, B->right);//对左右都进行判断
}
};