/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
void dfs(TreeNode* root, int& depth, int loof) {
if(root == NULL) return;//当前楼层不是有效楼层
depth = max(depth, loof);//记录最大楼层
dfs(root->left, depth, loof + 1);//向左遍历,求解最大楼层
dfs(root->right, depth, loof + 1);//向右遍历,求解最大楼层
}
public:
bool isCompleteTree(TreeNode* root) {
deque<TreeNode*> Deque;
Deque.push_back(root);
vector<string> ordered;//记录序列化后的结果
int cnt = 0, depth = 0;
dfs(root, depth, 1);//求出树的深度
while(!Deque.empty()) {//对树的每一层进行序列化
TreeNode* x = Deque.front();
Deque.pop_front();
//序列化
ordered.emplace_back(x == NULL ? "NULL" : to_string(x->val));
//添加状态
if(x == NULL) continue;
Deque.push_back(x->left);
Deque.push_back(x->right);
}
bool flag = false;
for(int i = 1; i <= depth; ++i) {//遍历数的每一层
for(int j = pow(2, i - 1) - 1; j < pow(2, i) - 1; ++j) {//遍历每一层的每一个元素
if(i == depth) {//最底层
if(ordered[j] == "NULL") flag = true;//如果最底层有元素为NULL,那么它之后的所有元素都不能为NULL,否则return false
if(flag && ordered[j] != "NULL") return false;
}else {//其他楼层的树不可以出现NULL
if(ordered[j] == "NULL") return false;
}
}
}
return true;
}
};
思路
我们可以将树的结构序列化,然后对序列化的元素分层,进行判断。
解法
利用dfs求解树的最大高度
利用deque的性质,配合while,实现按照树每一层的顺序遍历,并且序列化
由树的深度可以反推每一层元素的个数,因此可以对序列化的结果进行按层遍历,判断是否符合标准
/**
* Definition for a binary tree node.
* 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) {
if(A == NULL || B == NULL) return false;
return dfs(A, B) || isSubStructure(A->left, B) || isSubStructure(A->right, B);
}
bool dfs(TreeNode* A, TreeNode* B) {
if(B == NULL) return true;
else if(A == NULL && B != NULL) return false;
else if(A->val != B->val) return false;
return dfs(A->left, B->left) && dfs(A->right, B->right);
}
};
思路
确定B是不是A的子树结果,最好的方式是遍历A的所有节点,以那些节点为根节点,判断B是否是他们的子结构。
这里,我们涉及到两个步骤
对于步骤二:我们可以用dfs解决
对于步骤二:我们可以用递归的方式求解
这就引出了双递归
双递归可以用双循环理解,一个递归函数控制一边的递归,另外一个递归函数控制每次递归后要做的事情(只不过这样的事情也需要递归完成)