FBI树-蓝桥571

读题:(说实话我就是读不懂题)

1

一个地方一开始我觉得不理解:“含0和1的串叫F串,FBI树是一种二叉树,它的结点类型包括F结点,B结点,I结点”,可是一个结点不就是0或者1吗

不是的!既然说某个结点是含0和1的串的结点,说明就是在说这个结点它是父结点,它的儿子或者孙子是包含0和1的,也就是B和I

2

长度为2^n的01串可以构造出二叉树,并且是按串的平均分的左右两边去分别构造左子树和右子树的,这告诉我们,串的值就是叶子结点啊(叶子结点:二叉树的最底层的结点)

3思路

所以我们只用从底向上,从叶子结点开始赋值,一直往上面走为各个父结点赋值即可,用的是dfs,可以记住常见的用法,一般构造二叉树经常用dfs;

另外,后序遍历就是另一个知识点啦。

4满二叉树已知叶子结点个数

1)

对于一个满二叉树,已知其叶子结点的个数为n,则这个树的所有结点个数为2n-1;

对于非满二叉树,所有结点的个数就是:n<结点总个数<2n-1。

2)

所以这道题叶子结点个数为2^n,总结点个数就是2^(n+1)-1。那为什么这棵FBI树是满二叉树呢:因为题目说了把这个串从中间分开左右分别构造左右子树,而且长度是2^n,很明显是偶数是可以被平均分的,那么左右子树的叶子结点个数都一样,其实并没有说这是一个满二叉树,只是用满二叉树来存储,因为叶子结点0或者1,就是只代表一个字母啊。

但是也没有说不能左右子树层数不一样吧:我觉得是最大限度是左右层数都是满的,而放什么放不放取决于到时候父结点的赋值吧

5满二叉树已知元素个数

一个满二叉树,已知有元素个数是m个,则需要4m个节点空间存放完全二叉树(极端情况)。

如何理解:m想做是叶子结点所在层的所有结点个数(包括此结点是空的和不空的),因为这个存储空间也是考虑了叶子结点所在层这些叶子结点的子节点(因为声明结构体的时候每个节点都是有左右子结点的)

其他知识点

1cin数组名+1,相当于从这个数组的第二个位置开始存数

    char s[4];//输入1234
    
    //这两个等价
//    cin>>s+1;
    scanf("%s",s+1);
    
    cout<<s[0]<<endl;//输出换行
    cout<<s[1]<<endl;//输出1
    for(int i=0;i<sizeof(s);i++)
    {
        cout<<s[i];
    }//输出123

2移位操作

p<<1

p<<1|1

完整代码

#include<iostream>
#include<vector>
#include<cmath>
using namespace std;
int n;
char s[1024],tree[4096];
//视作箭头,左乘右除
int ls(int p)
{
	return p<<1;//p*2
}
int rs(int p)
{
	return p<<1|1;//p*2+1
}
void build_fbi(int p,int left,int right)
{
	if(left==right)//
	{
		if(s[right]=='1')
		{
			tree[p]='I';
		}
		else{
			tree[p]='B';
		}
		return;
	}
	
	//没走到叶子结点,就继续二分往下走
	int mid=(left+right)/2;
	build_fbi(ls(p),left,mid);
	build_fbi(rs(p),mid+1,right);
	
	if(tree[ls(p)]=='B'&&tree[rs(p)]=='B')
	{
		tree[p]='B';
	}
	else if(tree[ls(p)]=='I'&&tree[rs(p)]=='I')
	{
		tree[p]='I';
	}
	else{
		tree[p]='F';
	}
}

void postorder(int p)//后序遍历,对于二叉树这个数组存放的,左右父
{
	//可以看见内部外部都是遵循左右父顺序
	if(tree[ls(p)])//如果当前节点有左儿子,则再以此左儿子作为父结点,去后序遍历他的子树
	{
		postorder(ls(p));
	}
	if(tree[rs(p)])
	{
		postorder(rs(p));
	}

	cout<<tree[p];
}

int main()
{
	cin>>n;
	cin>>s+1;
	build_fbi(1,1,strlen(s+1));//参数:此节点,此节点左,此节点右
	postorder(1);//从根结点往里走,二叉树的遍历都是这样
	
	return 0;
}

测试用例:

输入:

3
10001011


输出:IBFBBBFIBFIIIFF

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
上选点是蓝桥杯Java题目中的一种类型,通常需要在给定的结构中选择一个或多个节点作为目标节点,并进行相应的操作。下面是一个简单的上选点蓝桥Java题解的示例: 题目描述: 给定一棵有N个节点的,每个节点上都有一个非负整数值。现在需要选择一些节点,使得选择的节点的值之和最大,且所选节点不能相邻(即选了一个节点,则其父节点和子节点都不能选)。请编写一个程序,计算出最大的节点值之和。 解题思路: 这是一个典型的动态规划问题。我们可以定义一个数组dp,其中dp[i]表示以第i个节点为根节点的子中所选节点的最大值之和。对于每个节点i,有两种情况: 1. 选择节点i:则其子节点都不能选,所以dp[i] = val[i] + dp[grandchild1] + dp[grandchild2] + ... 2. 不选择节点i:则其子节点可以选择或不选择,所以dp[i] = max(dp[child1], dp[child2], ...) 根据以上思路,我们可以使用递归或者迭代的方式来计算dp数组。最终,所求的最大值即为dp,其中1表示根节点。 代码示例: ```java public class TreeSelectPoint { public static void main(String[] args) { int[] values = {0, 1, 2, 3, 4, 5}; // 节点值数组,下标从1开始 int[][] edges = {{1, 2}, {1, 3}, {2, 4}, {2, 5}}; // 的边关系数组 int n = values.length - 1; // 节点个数 int[] dp = new int[n + 1]; // 动态规划数组 // 构建的邻接表 List<List<Integer>> adjacencyList = new ArrayList<>(); for (int i = 0; i <= n; i++) { adjacencyList.add(new ArrayList<>()); } for (int[] edge : edges) { int u = edge[0]; int v = edge[1]; adjacencyList.get(u).add(v); adjacencyList.get(v).add(u); } dfs(1, -1, values, adjacencyList, dp); // 从根节点开始进行深度优先搜索 System.out.println(dp[1]); // 输出最大节点值之和 } private static void dfs(int cur, int parent, int[] values, List<List<Integer>> adjacencyList, int[] dp) { dp[cur] = values[cur]; // 初始化当前节点的dp值为节点值 for (int child : adjacencyList.get(cur)) { if (child != parent) { // 避免重复访问父节点 dfs(child, cur, values, adjacencyList, dp); dp[cur] += dp[child]; // 更新当前节点的dp值 } } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值