题目## 题目
解题思路
这是一个二叉树的递归遍历问题。需要判断树B是否是树A的子树,关键是要正确处理树的结构比较。
关键点:
- 递归遍历树A的每个节点
- 判断以当前节点为根的子树是否与B相同
- 正确处理空节点情况
- 区分子树和部分结构的概念
算法步骤:
- 遍历树A的每个节点
- 对每个节点判断是否与B相同
- 递归比较子树结构
代码
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class IdenticalTree {
public:
bool chkIdentical(TreeNode* A, TreeNode* B) {
// 如果A为空,无法包含任何子树
if (A == nullptr) {
return false;
}
// 如果B为空,认为是A的子树
if (B == nullptr) {
return true;
}
// 检查当前节点开始的子树是否相同
if (isSameTree(A, B)) {
return true;
}
// 递归检查A的左右子树
return chkIdentical(A->left, B) || chkIdentical(A->right, B);
}
private:
bool isSameTree(TreeNode* A, TreeNode* B) {
// 两个都为空,认为相同
if (A == nullptr && B == nullptr) {
return true;
}
// 其中一个为空,另一个不为空,不相同
if (A == nullptr || B == nullptr) {
return false;
}
// 检查当前节点值是否相同
if (A->val != B->val) {
return false;
}
// 递归检查左右子树
return isSameTree(A->left, B->left) && isSameTree(A->right, B->right);
}
};
public class IdenticalTree {
public boolean chkIdentical(TreeNode A, TreeNode B) {
// 如果A为空,无法包含任何子树
if (A == null) {
return false;
}
// 如果B为空,认为是A的子树
if (B == null) {
return true;
}
// 检查当前节点开始的子树是否相同
if (isSameTree(A, B)) {
return true;
}
// 递归检查A的左右子树
return chkIdentical(A.left, B) || chkIdentical(A.right, B);
}
// 判断两棵树是否完全相同
private boolean isSameTree(TreeNode A, TreeNode B) {
// 两个都为空,认为相同
if (A == null && B == null) {
return true;
}
// 其中一个为空,另一个不为空,不相同
if (A == null || B == null) {
return false;
}
// 检查当前节点值是否相同
if (A.val != B.val) {
return false;
}
// 递归检查左右子树
return isSameTree(A.left, B.left) && isSameTree(A.right, B.right);
}
}
# -*- coding:utf-8 -*-
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class IdenticalTree:
def chkIdentical(self, A, B):
# 如果A为空,无法包含任何子树
if A is None:
return False
# 如果B为空,认为是A的子树
if B is None:
return True
# 检查当前节点开始的子树是否相同
if self.isSameTree(A, B):
return True
# 递归检查A的左右子树
return self.chkIdentical(A.left, B) or self.chkIdentical(A.right, B)
def isSameTree(self, A, B):
# 两个都为空,认为相同
if A is None and B is None:
return True
# 其中一个为空,另一个不为空,不相同
if A is None or B is None:
return False
# 检查当前节点值是否相同
if A.val != B.val:
return False
# 递归检查左右子树
return self.isSameTree(A.left, B.left) and self.isSameTree(A.right, B.right)
算法及复杂度
- 算法:递归遍历
- 时间复杂度: O ( N ∗ M ) \mathcal{O(N*M)} O(N∗M),其中 N N N 是 A A A 树的节点数, M M M 是 B B B 树的节点数
- 空间复杂度: O ( m a x ( H 1 , H 2 ) ) \mathcal{O(max(H1, H2))} O(max(H1,H2)),其中 H 1 H1 H1 和 H 2 H2 H2 分别是 A A A 和 B B B 的高度,用于递归栈空间
#题解
##题目难度:简单难度
##知识点:数学逻辑
分析:主要考虑输出格式,由于N=3k+1,那么前K行每行输出2个字符,后k+1行输出1个字符。对于前k行,第一行:第一列输出字符,空格数为m=2*k-1,在输出第二个字符;第二行:先空格1,输出字符,空格m-=2个(在前一行的基础上减少2个),输出第二个字符,依次类推…。关于后K+行,每行在输出字符前空格数为k。
N=7=3k+1,k=2(前两行输出两个字符,后三行输出1个字符),前k行中,n表示第一个字符前的空格数,m为输出第一个字符后的空格数。后k+1行,输出字符前的空格数用k表示。
#include<iostream>
#include<vector>
using namespace std;
int main(){
int N,k,m,i,n;
string line;
cin>>N;
char ch;
vector<char> v;
i=N;
while(i--) {
cin>>ch;
cin>>noskipws;//在读入第一个字符后设置可以读入空格
v.push_back(ch);
}
k=(N-1)/3;
m=2*k-1;
i=0,n=1;
for(int x=n;x<=k;x++){
for(int y=1;y<n;y++) printf(" "); cout<<v[i++]; for(int y="1;y<=k;y++)" cout<<v[i++]<<endl; m-="2;" n++; } x="1;x<=k+1;x++){" return 0; ```####【注】本题输入的空格也算是字符,所以在接收到第一个字符后,需要添加代码 ` cin>>noskipws;`使得可以读取空格。</n;y++)></char></vector></iostream>