PPOJ刷题-3
Posted Mr.wu123
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PPOJ刷题-3相关的知识,希望对你有一定的参考价值。
PPOJ刷题-3
1265: 最近公共祖先
题目描述
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
输入
输入两行。
第一行按照先序输入一棵二叉树,其中空节点用 -1 表示。
第二行输入两个结点的值val1, val2 , 输出该结点的双亲节点的val.(数据保证所有节点val的值都不相同)
输出
输出一行,代表最近公共祖先的val。
样例输入
3 5 6 -1 -1 2 7 -1 -1 4 -1 -1 1 0 -1 -1 8 -1 -1
5 1
样例输出
3
#include<bits/stdc++.h>
using namespace std;
const int N=100;
//先序遍历建立二叉树,然后对其进行先序遍历,
//如果某个结点的左子树和右子树都找到了权值为a和b的结点,则该节点就是最近公共结点
struct TreeNode
int val;
TreeNode *left,*right;
;
void build(TreeNode * &T)
int x;
cin>>x;
if(x==-1)
T==NULL;
return ;
T=new TreeNode;
T->val=x;
T->left=T->right=NULL;
build(T->left);
build(T->right);
TreeNode *Find(TreeNode *T,int a,int b)
//如果该节点权值为a或b,或者该节点为空,返回该结点
if(T==NULL||T->val==a||T->val==b) return T;
//递归查找左子树和右子树,将结果分别保存在l和r
TreeNode *l=Find(T->left,a,b),*r=Find(T->right,a,b);
//如果在左右子树找到了,就返回该节点
if(l && r) return T;
//否则说明在同一子树上;对于一个结点是另一个结点祖先的情况,先找到的结点就是最近公共祖先
else return l?l:r;
int main()
TreeNode * T=NULL;
build(T);
int a,b;
cin>>a>>b;
cout<<Find(T,a,b)->val<<endl;
return 0;
1266: 二叉树的直径
题目描述
二叉树的直径是指二叉树中相距最远的两个点的距离。如下图所示二叉树,最远的两个点是7和13或者 4和13,故二叉树直径为6.
输入
输入一行,按照先序输入一棵二叉树,其中空节点用 -1 表示。
输出
输出一行代表二叉树的直径。
样例输入
8 3 1 -1 -1 6 4 -1 -1 7 -1 -1 10 -1 14 13 -1 -1 -1
样例输出
6
#include<bits/stdc++.h>
using namespace std;
const int N=100;
//先序遍历建立二叉树,求二叉树中相距最远的两个点的距离
//只需要每个结点的的左子树的最大深度+右子树的最大深度
struct TreeNode
int val;
TreeNode *left,*right;
;
int MaxL=0;
void build(TreeNode * &T)
int x;
cin>>x;
if(x==-1)
T==NULL;
return ;
T=new TreeNode;
T->val=x;
T->left=T->right=NULL;
build(T->left);
build(T->right);
//求解以该节点为根节点的最大深度
int Depth(TreeNode *T,int h)
//若该结点为空,就返回深度
if(T==NULL) return h;
//分别求出左右子树的深度
int l=Depth(T->left,h+1),r=Depth(T->right,h+1);
return max(l,r);
//寻找二叉树中相距最远的两个点的距离
void Find(TreeNode *T)
if(T==NULL) return;
int l,r;
//左子树不为空则求左子树的深度,为空则深度为0
l=T->left?Depth(T->left,0):0;
//右子树不为空则求右子树的深度,为空则深度为0
r=T->right?Depth(T->right,0):0;
if(MaxL<l+r) MaxL=l+r;
Find(T->left);
Find(T->right);
int main()
TreeNode * T=NULL;
build(T);
MaxL=0;
Find(T);
cout<<MaxL<<endl;
return 0;
1364: 删除给定值的叶子节点
题目描述
PIPI有一棵二叉树和一个整数 target ,请你删除所有值为 target 的 叶子节点 。
注意,一旦删除值为 target 的叶子节点,它的父节点就可能变成叶子节点;如果新叶子节点的值恰好也是 target ,那么这个节点也应该被删除。
输入
第一行按照先序输入树T,其中空节点用 -1 表示。
第二行输入target
输出
按照先序输出删完之后的二叉树。
样例输入
1 2 2 -1 -1 -1 3 2 -1 -1 4 -1 -1
2
样例输出
1 3 4
#include<bits/stdc++.h>
using namespace std;
const int N=100;
//采用后序遍历进行查找,因为要先知道子节点被删除没有;
//记录每一个结点的父亲结点,以及当前结点是父节点的左孩子还是右孩子(0左1右)
//如果当前结点值为target并且左右子树都为空,那就将父节点的左(右)孩子置空
struct TreeNode
int val;
TreeNode *left,*right;
;
void build(TreeNode * &T)
int x;
cin>>x;
if(x==-1)
T==NULL;
return ;
T=new TreeNode;
T->val=x;
T->left=T->right=NULL;
build(T->left);
build(T->right);
void Delete(TreeNode *root,TreeNode *fa,int son,int target)//son=0左孩子,son=1右孩子
if(!root) return;
Delete(root->left,root,0,target);
Delete(root->right,root,1,target);
//如果结点值为target,且左右子树为空就删除
if(root->val==target && root->left==NULL && root->right==NULL)
if(son==0) fa->left=NULL;
else fa->right=NULL;
void Print(TreeNode *T)//先序输出
if(T==NULL) return;
printf("%d ",T->val);
Print(T->left);
Print(T->right);
int main()
TreeNode * T=NULL;
build(T);
int target;
cin>>target;
Delete(T,T,-1,target);
//根节点为target
if(T->val==target && T->left==NULL &&T->right==NULL)
T=NULL;
Print(T);
return 0;
1365: 祖父结点为偶数的节点
题目描述
PIPI有一棵二叉树,他想知道所有祖父结点值为偶数的结点值之和。
输入
输入包含一行,先序输入一棵二叉树,空节点用-1表示。
输出
输出为满足条件的结点值之和。
样例输入
6 7 2 9 -1 -1 -1 7 1 -1 -1 4 -1 -1 8 1 -1 -1 3 -1 5 -1 -1
样例输出(2+7+1+3+5=18)
18
#include<bits/stdc++.h>
using namespace std;
const int N=100;
//每次遍历保存该节点的父节点和祖父结点,判断祖父结点是否为偶数即可
//递归时,当前结点变父节点,父节点变祖父结点
struct TreeNode
int val;
TreeNode *left,*right;
;
int ans=0;//统计数值之和
void build(TreeNode * &T)
int x;
cin>>x;
if(x==-1)
T==NULL;
return ;
T=new TreeNode;
T->val=x;
T->left=T->right=NULL;
build(T->left);
build(T->right);
void DFS(TreeNode *T,TreeNode *fa,TreeNode *gfa)//进行中序遍历
if(!T) return;
DFS(T->left,T,fa);
//祖父结点存在且为偶数
if(gfa&&gfa->val%2==0) ans+=T->val;
DFS(T->right,T,fa);
int main()
TreeNode * T=NULL;
build(T);
DFS(T,NULL,NULL);
cout<<ans<<endl;
return 0;
1369: 二叉树的最大深度
题目描述
给定一个二叉树,找出其最大深度。
最大深度是从根节点到最远叶子节点的最长路径上的节点数量。
输入
输入一行,按照先序输入一棵二叉树,其中空节点用 -1 表示。
输出
输出一行代表二叉树的最大深度。
样例输入
1 2 -1 -1 3 4 -1 -1 -1
样例输出
3
#include<bits/stdc++.h>
using namespace std;
const int N=100;
struct TreeNode
int val;
TreeNode *left,*right;
;
void build(TreeNode * &T)
int x;
cin>>x;
if(x==-1)
T==NULL;
return ;
T=new TreeNode;
T->val=x;
T->left=T->right=NULL;
build(T->left);
build(T->right);
int Height(TreeNode *T,int h)
if(T==NULL) return h;
return max(Height(T->left,h+1),Height(T->right,h+1));
int main()
TreeNode * T=NULL;
build(T);
cout<<Height(T,0)<<endl;
return 0;
1370: 高度平衡的二叉树
题目描述
给定一个二叉树,判断它是否是高度平衡的二叉树。
一棵高度平衡二叉树定义为:一个二叉树每个节点的左右两个子树的高度差的绝对值不超过1。
输入
输入一行,按照先序输入一棵二叉树,其中空节点用 -1 表示。
输出
若是则输出YES,否则输出NO。
样例输入
1 2 -1 -1 3 4 -1 -1 -1
样例输出
YES
#include<bits/stdc++.h>
using namespace std;
const int N=100;
//用flag标记二叉树是否平衡,对每个结点计算两个子树的高度差
struct TreeNode
int val;
TreeNode *left,*right;
;
int flag=1;
void build(TreeNode * &T)
int x;
cin>>x;
if(x==-1)
T==NULL;
return ;
T=new TreeNode;
T->val=x;
T->left=T->right=NULL;
build(T->left);
build(T->right);
int Height(TreeNode *T,int h)
if(T==NULL) return h;
return max(Height(T->left,h+1),Height(T->right,h+1));
void Judge(TreeNode *T)
if(!flag||T==NULL) return;
if(abs(Height(T->left,0)-Height(T->right,0))>1) flag=0;
//继续递归判断左右子树
Judge(T->left);
Judge(T->right);
int main()
TreeNode * T=NULL;
build(T);
Judge(T);
if(flag)
printf("YES\\n");
else
printf("NO\\n");
return 0;
1371: 求根到叶子结点数字之和
题目描述
给定一个二叉树,它的每个结点都存放一个1-9的数字,每条从根到叶子节点的路径都代表一个数字。
例如,从根到叶子节点路径 1->2->3 代表数字 123。
计算从根到叶子节点生成的所有数字之和,答案保证在int范围。
输入
输入一行,按照先序输入一棵二叉树,其中空节点用 -1 表示。
输出
输出根到叶子节点生成的所有数字之和。
样例输入
1 2 -1 -1 3 4 -1 -1 -1
样例输出
146
#include<bits/stdc++.h>
using namespace std;
const int N=100;
//用变量sum来统计所有数字之和,每次递归到了根节点,就把数字加到sum中,然后结束递归
struct TreeNode
int val;
TreeNode *left,*right;
;
int sum=0;
void build(TreeNode * &T)
int x;
cin>>x;
if(x==-1)
T==NULL;
return ;
T=new TreeNode;
T->val=x;
T->left=T->right=NULL;
build(T->left);
build(T->right);
void Plus(TreeNode *T,int ans)
//如果为叶子结点,结束递归
if(T->left==NULL&&T->right==NULL) sum+=ans*10+T->val;
//否则继续在左右子树递归查找叶子结点
if(T->left!=NULL) Plus(T->left,ans*10+T->val);
if(T->right!=NULL) Plus(T->right,ans*10+T->val);
int main()
TreeNode * T=NULL;
build(T);
Plus(T,0);
cout<<sum<<endl;
return 0;
1372: 找树左下角的值
题目描述
给定一个二叉树,在树的最后一行找到最左边的值。
输入
输入一行,按照先序输入一棵二叉树,其中空节点用 -1 表示。
输出
输出树的最后一行最左边的值。
样例输入
1 2 -1 -1 3 4 -1 -1 -1
样例输出
4
#include<bits/stdc++.h>
using namespace std;
//按照先序遍历遍历整棵树,保存深度最深的第一个遍历到的叶子结点的值
const int N=100;
struct TreeNode
int val;
TreeNode *left,*right;
;
int H=0,x;
void build(TreeNode * &T)
int x;
cin>>x;
if(x==-1)
T==NULL;
return ;
T=new TreeNode;
T->val=x;
T->left=T->right=NULL;
build(T->left);
build(T->right);
void findk(TreeNode *T,int h)
//如果是叶子结点
if(T->left==NULL&&T->right==NULLPPOJ刷题-2