【04 重建二叉树】
题目描述
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
思路:
1) 二叉树的构建,赋值,左右子树的便利?
2) 由前序列表,中序列表 恢复左右子树: 前序的根,在中序中划分左右子树,递归重构左右子树
3) C++ 读取未知长度的数组,以回车判断数组结束
样例:
1 2 4 7 3 5 6 8
4 7 2 1 5 3 8 6
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
//根据前序列表和中序列表,重构二叉树。前序的第一个元素为树的根 可以在中序列表划分出 左右子树
if(pre.empty()||vin.empty())
return NULL;
if(pre.size()!=vin.size())
return NULL;
TreeNode *p;
p = (TreeNode*)malloc(sizeof(TreeNode));
int i=0,mid=0;
for(i=0;i<vin.size();i++)
{
if(pre[0]==vin[i])
mid=i;
}
vector<int> pre_left,pre_right,vin_left,vin_right;
for(i=0;i<mid;i++)
{
pre_left.push_back(pre[i+1]);
vin_left.push_back(vin[i]);
}
for(i=mid+1;i<vin.size();i++)
{
pre_right.push_back(pre[i]);
vin_right.push_back(vin[i]);
}
p->val = pre[0];
p->left = reConstructBinaryTree(pre_left,vin_left);
p->right = reConstructBinaryTree(pre_right,vin_right);
return p;
}
【17 树的子结构】
题目描述
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
思路:
1) 首先判断,递归判断A和B是否是同一棵树;否则判断左子树或右子树 与 B是否为同一棵树
2) 递归判断 两棵树是否为同一颗树:判断 的各个节点是否都相同
bool SameTree(TreeNode* pRoot1, TreeNode* pRoot2) // 递归判断 两棵树的元素是否都相同
{
bool val;
if(pRoot2==NULL)
return true;
if(pRoot1==NULL)
return false;
if(pRoot1->val!=pRoot2->val)
return false;
else
return SameTree(pRoot1->left,pRoot2->left) && SameTree(pRoot1->right,pRoot2->right);
}
bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2) // 递归判断 二叉树 2 是不是二叉树1 的子结构
{
bool val = false;
if(pRoot1==NULL ||pRoot2==NULL)
return val;
return SameTree(pRoot1,pRoot2) | HasSubtree(pRoot1->left,pRoot2) || HasSubtree(pRoot1->right,pRoot2);
}
【18 二叉树的镜像】
题目描述
操作给定的二叉树,将其变换为源二叉树的镜像。
输入描述:
二叉树的镜像定义:源二叉树
8
/ \
6 10
/ \ / \
5 7 9 11
镜像二叉树
8
/ \
10 6
/ \ / \
11 9 7 5
思路:
1) 递归翻转 左右子树
2)非递归翻转, 利用堆存放在 节点
void Mirror(TreeNode *pRoot) //递归实现 翻转 二叉树
{
TreeNode *p;
if(pRoot==NULL)
{
return;
}
else{
p= pRoot->left;
pRoot->left = pRoot->right;
pRoot->right = p;
Mirror(pRoot->left);
Mirror(pRoot->right);
//cout<<pRoot->left->val<<','<<pRoot->right->val<<endl;
}
}
//非递归实现
void Mirror_non(TreeNode *pRoot)
{
if(pRoot==NULL)
return;
stack<TreeNode*> s; //栈 用来保存 节点。我们还需要翻转左右子树
s.push(pRoot);
while(!s.empty())
{
TreeNode *p = s.top();
cout<<s.size()<<','<<p->val<<endl;
s.pop();
TreeNode *tmp = p->left;
p->left = p->right;
p->right = tmp;
if(p->left!=NULL)
{
s.push(p->left);
cout<<p->val<<"left:"<<p->left->val<<endl;
}
if(p->right!=NULL){
s.push(p->right);
cout<<p->val<<"right:"<<p->right->val<<endl;
}
}
}
【22 从上到下打印二叉树】
题目描述
从上往下打印出二叉树的每个节点,同层节点从左至右打印。
思路:
1) 借助队列 存储 节点
vector<int> PrintFromTopToBottom(TreeNode* root) { //层次遍历 借助 队列
queue<TreeNode*> q;
vector<int> result;
if(root)
q.push(root);
while(!q.empty())
{
TreeNode* cur = q.front();
q.pop();
result.push_back(cur->val);
if(cur->left)
{
q.push(cur->left);
}
if(cur->right)
{
q.push(cur->right);
}
}
return result;
}
【23 二叉树的后序遍历】
题目描述
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
bool VerifySquenceOfBST(vector<int> s) {
if(s.size()==1)
return true;
if(s.size()==0) //本题 认定,[] 为非二叉搜索树的后序遍历列表
return false;
int mid=0,end = s.size()-1, i=0;
while(mid<end && s[mid]<s[end]) //s[end]是根节点,是中间值
{
mid++;
}
vector<int> left,right;
for(i=0;i<mid;i++)
{
left.push_back(s[i]); //左子树的后序遍历列表
}
for(i=mid;i<end;i++)
{
if(s[i]<s[end]) // 右子树 比 根节点 大,返回 false,表示不满足二叉搜索树的特征
return false;
right.push_back(s[i]); //右子树的后续遍历列表
}
bool l=true,r=true;
// !! 递归 时判断 是不是 左/右子树 为空的情况,某一子树为空,则只需判断 右/左子树 的情况
if(!left.empty())
l = VerifySquenceOfBST(left);
if(!right.empty())
r = VerifySquenceOfBST(right);
return l&&r;
}