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 @ 2024-06-11 15:18  五月江城  阅读(111)  评论(0编辑  收藏  举报