PTA----字母子集合

C语言实现子集生成算法
博客分享了一道关于生成数组子集的问题,通过C语言实现。代码中定义了一个函数`my_print`用于打印从A到Z的字符数组中指定长度子集的所有组合。例如,输入2时,输出其所有子集:空集、A、B和AB。程序通过位运算计算子集个数并遍历输出。

最近刷题遇见一个不错的题,分享一下!

 

这题啥意思呢?先写一个数组存A-Z,输入一个数,输出它的所有子集(包括空集)如果输入3,代表A, B, C的所有子集,并用他们三个表示。

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
void my_print(char a1[], int count)

{
    int i, j, tmp;
    int Sum = 1 << count;          // 子集合的个数
    for (i = 0; i < Sum; i++)
    {
        j = i;
        tmp = 0;
        printf("{");
        while (j)
        {
            if (j & 1)   //按位与运算
            {
                printf(" %c", a1[tmp]);   //打印字母
            }
            j >>= 1;
            tmp++;
        }

        printf(" }\n");
    }
}
int main()
{
    char a[26] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    int num;
    scanf("%d", &num);
    my_print(a, num);

    return 0;

}

咱来具体看一下-------

输入2,那他的子集有 0(代表空集) ,A,  B,  AB四个对吧。

Sum代表子集个数,Sum=1<<2(1左移2)变成4,所以运行4次

同理,输入3和2的逻辑一模一样。 

<think>嗯,用户想解决PTA平台上树的同构问题的Python实现。首先,我需要回忆一下树的同构的定义。根据引用[3],同构的树可以通过交换某些节点的左右子树来变得结构相同。比如图1中的例子,交换A、B、G的左右孩子后,两棵树结构相同。而图2则不行。所以判断同构的关键在于递归比较根节点的值和子树结构是否匹配,包括可能交换左右子树的情况。 接下来,用户需要Python的解题思路和代码实现。首先,我得考虑输入的处理。根据引用[2],输入包括每个节点的字母、左孩子和右孩子的编号。对于每个树,先读取n,然后n行数据。节点编号是0到n-1,空孩子用“-”表示。所以需要将这些输入转换为节点对象或字典来存储每个节点的左右子节点。 然后,如何找到树的根节点呢?通常根节点没有父节点,所以可以通过遍历所有节点,找出没有出现在任何子节点位置的编号。比如,用一个集合记录所有子节点,剩下的那个就是根节点。 接下来,核心算法是递归判断两棵树是否同构。根据引用[1],核心在于递归比较。首先,如果两棵树都为空,返回True。如果一个空一个不空,返回False。然后,比较当前两个根节点的值是否相同。如果不同,直接False。接着,递归判断两种情况:不交换左右子树的情况,或者交换其中一个树的左右子树的情况。只要有一种情况满足即可。 那具体的步骤应该是这样的:对于两棵树的当前节点,比较它们的值。然后检查它们的左右子树是否相同,或者是否在交换左右后相同。比如,树1的左子树和树2的左子树是否同构,同时右子树也同构;或者树1的左子树和树2的右子树同构,同时右子树和树2的左子树同构。这两种情况满足其一即可。 需要注意边界条件,比如当其中一棵子树为空的情况。例如,如果树1的左子树为空,而树2的右子树也为空,那么交换后可能匹配。 然后,代码实现部分。需要将输入转换为节点结构。可以用字典来存储每个节点的左右孩子。例如,对于每个节点,存储其左孩子和右孩子的编号,如果是“-”则标记为None或者-1。然后,找到根节点后,递归判断。 例如,构建树的结构时,可以用一个列表或字典,每个节点存储左和右子节点的索引。例如,nodes1是一个字典,键是节点编号,值是一个包含左和右子节点的元组。然后,递归函数需要接收两个当前节点的编号,以及对应的两棵树的节点字典。 还要处理节点值为空的情况,比如当某个节点不存在时,需要返回对应的判断。 代码的大致流程: 1. 读取输入,构建两棵树的节点结构。 2. 找到两棵树的根节点。 3. 使用递归函数判断是否同构。 举个例子,假设输入的树结构如下: 树1: 3 A 1 2 B - - C - - 树2: 3 A 2 1 B - - C - - 这两棵树的根节点都是0号节点。递归比较时,根节点的值相同,然后比较左左和右右是否同构,或者左右和右左是否同构。这时候,交换左右子树后,可以得到相同结构,所以返回True。 在Python中,如何处理节点的读取呢?可以用一个函数来读取n行输入,每个节点存储字母、左、右。例如: def read_tree(): n = int(input()) nodes = {} children = set() for i in range(n): parts = input().split() letter = parts[0] left = parts[1] if parts[1] != '-' else -1 right = parts[2] if parts[2] != '-' else -1 if left != -1: left = int(left) children.add(left) if right != -1: right = int(right) children.add(right) nodes[i] = (letter, left, right) # 找根节点,即没有在children中的节点 root = None for i in range(n): if i not in children: root = i break return root, nodes 然后,递归函数: def is_isomorphic(root1, root2, nodes1, nodes2): # 都为空 if root1 == -1 and root2 == -1: return True # 一个空,另一个不空 if (root1 == -1) != (root2 == -1): return False # 节点值不同 node1 = nodes1[root1] node2 = nodes2[root2] if node1[0] != node2[0]: return False # 比较不交换的情况和交换的情况 return (is_isomorphic(node1[1], node2[1], nodes1, nodes2) and is_isomorphic(node1[2], node2[2], nodes1, nodes2)) or \ (is_isomorphic(node1[1], node2[2], nodes1, nodes2) and is_isomorphic(node1[2], node2[1], nodes1, nodes2)) 这样可能会有问题,比如,当两个子树结构不同,但交换后可能匹配。例如,左子树和右子树交换后是否满足条件。 但需要考虑节点为空的情况,所以在递归调用时,需要处理当某个子节点为-1的情况。 然后,测试这个函数。例如,当根节点的左右子树交换后,是否返回True。 可能需要注意,当两个子树结构在交换后必须同时满足同构。例如,左子树和对方的右子树同构,同时右子树和对方的左子树同构。 此外,还需要处理当两个树的结构不同,但字母相同的情况下是否能够正确判断。 可能存在的错误情况:比如,节点值相同,但子树结构无法匹配,即使交换左右。 例如,树1的根A有左子树B和右子树C,而树2的根A有左子树C和右子树B。此时交换后是否结构相同? 如果B和C的结构不同,那么可能无法匹配。 另一个情况是,树1的根A的左子树是B,而树2的根A的右子树是B,但B的结构不同,这时候应该返回False。 所以递归必须严格比较子树的结构。 最后,将上述思路整理成代码,并处理输入输出。 可能的测试用例: 输入两棵相同的树,返回Yes;输入交换左右子树的树,返回Yes;输入结构不同的树,返回No。 例如,引用[3]中的例子,如果两棵树在交换某些节点的子树后结构相同,则返回Yes。 所以,最终的Python代码大致结构应该是这样的: 读取两棵树的结构,找到根节点,然后调用递归函数判断是否同构。 需要注意的是,Python中如何处理节点的编号,特别是在转换输入时,是否需要将字符串转换为整数,比如将“-”转换为-1。 此外,如果某个树为空(n=0),如何处理?题目中输入的n是非负整数,所以当n=0时,没有节点。此时如果另一棵树也是n=0,则同构;否则不同构。 综上,完整的Python代码可能如下: 读取两棵树的结构,处理根节点的查找,然后递归判断。 现在,将这些思路转化为具体的代码步骤,并确保正确处理所有边界情况。</think>### PTA树的同构问题Python解题思路 #### 问题分析 树的同构指两棵树通过交换某些节点的左右子树后结构相同[^3]。解决该问题的核心在于递归比较两棵树的结构是否匹配,允许左右子树交换。 #### 输入处理 1. **输入格式**:每棵树输入包含节点数$n$,随后$n$行描述节点的字母、左孩子和右孩子的编号(空为`-`)[^2]。 2. **数据结构**:使用字典存储每个节点的左/右孩子编号,如`nodes1[i] = (val, left, right)`。 #### 算法步骤 1. **寻找根节点**:根节点是没有出现在任何子节点位置的编号。 2. **递归判断同构**: - 若两棵树均为空,返回`True`。 - 若一棵空另一非空,返回`False`。 - 若当前节点字母不同,返回`False`。 - 递归比较两种情况: 1. **不交换左右子树**:比较左子树与左子树、右子树与右子树。 2. **交换左右子树**:比较左子树与右子树、右子树与左子树。 #### 代码实现 ```python def read_tree(): n = int(input()) if n == 0: return -1, {} # 空树处理 nodes = {} children = set() for _ in range(n): val, left, right = input().split() left = int(left) if left != '-' else -1 right = int(right) if right != '-' else -1 nodes[_] = (val, left, right) if left != -1: children.add(left) if right != -1: children.add(right) root = -1 for i in range(n): if i not in children: root = i break return root, nodes def is_isomorphic(root1, root2, tree1, tree2): # 两树均为空 if root1 == -1 and root2 == -1: return True # 一棵空另一非空 if (root1 == -1) ^ (root2 == -1): return False # 当前节点值不同 node1 = tree1[root1] node2 = tree2[root2] if node1[0] != node2[0]: return False # 不交换左右子树的情况 case1 = is_isomorphic(node1[1], node2[1], tree1, tree2) and \ is_isomorphic(node1[2], node2[2], tree1, tree2) # 交换左右子树的情况 case2 = is_isomorphic(node1[1], node2[2], tree1, tree2) and \ is_isomorphic(node1[2], node2[1], tree1, tree2) return case1 or case2 # 主程序 root1, tree1 = read_tree() root2, tree2 = read_tree() if is_isomorphic(root1, root2, tree1, tree2): print("Yes") else: print("No") ``` #### 代码说明 1. **`read_tree`函数**:读取输入并构建树结构,返回根节点和节点字典。 2. **`is_isomorphic`函数**:递归判断两棵树是否同构,允许左右子树交换。 3. **边界处理**:空树、节点值不同、子树结构不匹配等情况。 #### 示例输入 ```text 3 A 1 2 B - - C - - 3 A 2 1 B - - C - - ``` 输出:`Yes`(交换左右子树后结构相同)。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值