三十天算法突破计划 Day 1
AC1
Problem,已知二叉树的前序遍历和后序遍历,求这个树的中序遍历的可能数目
思路
首先说明两条性质
一 在前序遍历中,若一个节点只有一个子节点,那么它一定在它的子节点的前面
二 在后序遍历中,若一个节点只有一个子节点,那么它一定在它的子节点的后面
对于一个树的前序遍历和后序遍历,我们考虑一个最小的单元,就是两个节点的树,在这个树里面,不管第二个节点是在左边还是在右边,都能得到一样的前序遍历结果和后序遍历的结果,所以在这个里面我们要找的就是只有一个支的节点。再根据上面的两个性质去进行查找有多少个单子节点的节点。
解答
#include <stdio.h>
#include <string.h>
#define N 20000
char s1[N];
char s2[N];
int ans;
int main()
{
scanf("%s%s",s1,s2);
for (int i = 0; i < strlen(s1)-1; i++)
for (int j = 1; j < strlen(s2); j++)
if(s1[i]==s2[j]&&s1[i+1]==s2[j-1]) ans++;
// 查找我们的节点
printf("%lld",1ll<<ans);
// 所有的可能
}
AC2
Problem求二叉树两个节点之间的距离,宽度,深度
在这里我们要先学习一下啊LCA问题————求两个子节点的最近公共祖先。就先论述一下LCA的一种解法吧(其实目前也只会这一种)
思路:先将两个节点调整到一个高度,即让一个变为与另外一个等高度的祖先,然后二者必然有一个公共祖先,他们的距离必然可以用一个二进制的数进行表示,需要跳跃的次数可以表示2的几种幂之和。
LCA模版题 ,大家不了解的可以去切题
下面是AC的代码
#include <stdio.h>
#include <iostream>
using namespace std;
#define N 1000
int lg[N];
int fa[N][N];
int dep[N];
struct node
{
int depth;
int father;
}node[N];
int cnt = 0;
int Lca(int x,int y)
{
if(node[x].depth < node[y].depth)
swap(x, y);
while (node[x].depth > node[y].depth)
{
x = fa[x][lg[node[x].depth - node[y].depth]];
}
if(x==y) return x;
for (int i = lg[node[x].depth]; i>=0; i--)
{
// printf("%d %d\n",fa[x][i-1],fa[y][i-1]);
if(fa[x][i]!=fa[y][i])
{
x = fa[x][i];
y = fa[y][i];
}
}
return fa[x][0];
}
// 上面这一部分是倍增的LCA代码
int main()
{
lg[0] = 0;
for(int i = 1; i < N; ++i) //预先算出log_2(i)的值,用的时候直接调用就可以了
lg[i] = lg[i-1] + (1 <<(lg[i-1]+1) == i); //看不懂的可以手推一下
int n,x,y;
int Depth = 0;
scanf("%d",&n);
node[1].depth = 1;
for (int i = 1; i < n; i++)
{
scanf("%d%d",&x,&y);
node[y].father = x;
node[y].depth = node[x].depth+1;
Depth = max(Depth,node[y].depth);
fa[y][0] = x;
for (int i = 1; i <= lg[node[y].depth]; i++)
{
fa[y][i] = fa[fa[y][i-1]][i-1];
}
dep[node[x].depth]++;
// 查找每个数的第2^i个祖先
}
int kuan = 0;
for (int i = 1; i <= Depth; i++)
{
kuan = max(kuan,dep[i]);
}
scanf("%d%d",&x,&y);
int LCA = Lca(x, y);
printf("%d\n",Depth);
printf("%d\n",kuan);
printf("%d",2*abs(node[x].depth - node[LCA].depth) + abs(node[y].depth - node[LCA].depth));
}