CSP历年复赛题-P5018 [NOIP2018 普及组] 对称二叉树

原题链接:https://www.luogu.com.cn/problem/P5018

题意解读:找到是对称二叉树的最大子树节点数。

解题思路:

1、先统计每一个节点为子树的节点数

int dfs1(int root)
{
    if(root == -1) return 0;
    return cnt[root] = dfs1(tree[root].l) + dfs1(tree[root].r) + 1;
}

2、再从根依次向下枚举每一个子节点,判断左右子树是否对称,如果对称则输出子树节点数,否则递归从左、右子树中找最大的对称子树节点数

int dfs2(int root)
{
    if(root == -1) return 0;
    if(check(tree[root].l, tree[root].r)) return cnt[root];
    else return max(dfs2(tree[root].l), dfs2(tree[root].r));
}

3、检查一个节点的左、右子树是否对称

如果左、右子树的根都是-1,则是对称

如果左、右子树节点数不相等,肯定不对称

如果左、右子树根节点权值不相等,肯定不对称

递归判断左子树的左子树是否和右子树的右子树对称,左子树的右子树是否和右子树的左子树对称

bool check(int left, int right)
{
    //左右都是空,只有根节点,也是对称的
    if(left == -1 && right == -1) return true;
    //左右子树节点数不一样,肯定不对称
    if(cnt[left] != cnt[right]) return false;
    //左右节点权值不同,也不对称
    if(tree[left].w != tree[right].w) return false;
    //递归判断左-左、右-右,左-右、右-左是否对称
    return check(tree[left].l, tree[right].r) && check(tree[left].r, tree[right].l);
}

时间复杂度分析:枚举每一个节点复杂度是n,如果从某个节点开始是对称,则需要递归logn次,总体复杂度n*logn

100分代码:

#include <bits/stdc++.h>
using namespace std;

const int N = 1000005;
int n;

struct node
{
    int l, r, w;
} tree[N];

int cnt[N]; //以每个节点为根的子树的节点数

//统计所有节点为根的子树的节点数
int dfs1(int root)
{
    if(root == -1) return 0;
    return cnt[root] = dfs1(tree[root].l) + dfs1(tree[root].r) + 1;
}

//检查以left,right为根的子树是否对称
bool check(int left, int right)
{
    //左右都是空,只有根节点,也是对称的
    if(left == -1 && right == -1) return true;
    //左右子树节点数不一样,肯定不对称
    if(cnt[left] != cnt[right]) return false;
    //左右节点权值不同,也不对称
    if(tree[left].w != tree[right].w) return false;
    //递归判断左-左、右-右,左-右、右-左是否对称
    return check(tree[left].l, tree[right].r) && check(tree[left].r, tree[right].l);
}

//枚举所有点,看左右是否对称,返回对称的最大子树节点数
int dfs2(int root)
{
    if(root == -1) return 0;
    if(check(tree[root].l, tree[root].r)) return cnt[root];
    else return max(dfs2(tree[root].l), dfs2(tree[root].r));
}

int main()
{
    cin >> n;
    for(int i = 1; i <= n; i++)
    {
        cin >> tree[i].w;
    }
    for(int i = 1; i <= n; i++)
    {
        cin >> tree[i].l >> tree[i].r;
    }

    dfs1(1);
    cout << dfs2(1);

    return 0;
}

 

posted @   五月江城  阅读(136)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
点击右上角即可分享
微信分享提示