首页 > 其他分享 >CSP历年复赛题-P5018 [NOIP2018 普及组] 对称二叉树

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

时间:2024-06-11 15:22:19浏览次数:20  
标签:return int tree NOIP2018 二叉树 对称 P5018 root 节点

原题链接: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;
}

 

标签:return,int,tree,NOIP2018,二叉树,对称,P5018,root,节点
From: https://www.cnblogs.com/jcwy/p/18242136

相关文章

  • 二叉树相关算法题汇总-go语言实现
    总结先序中序后序遍历就能解决一些算法题。层次遍历使用队列。从左子树、右子树获取答案,然后结合根节点来计算答案。前缀树,比Hashset更稳定。O(1),只不过占内存。trie树。递归。递归,递归。到叶子节点收集答案。然后移除路径。packagemainimport( "fmt" "math......
  • 二叉树的所有路径-力扣
    这道题目需要返回给定二叉树所有从根节点到叶子节点的路径,那么对二叉树进行深度优先搜索,遇到节点就将其加到路径中,如果这个节点的左右子节点都为空,那么它就是一个叶子节点,将这条路径加入到结果数组中。这里将int转换为string使用了to_string()函数。/***Definition......
  • CSP历年复赛题-P5017 [NOIP2018 普及组] 摆渡车
    原题链接:https://www.luogu.com.cn/problem/P5017题意解读:先将问题进行抽象、建模。设一条数轴,从左到右,每个点对应一个时刻,每个时刻可能有多个人到达,然后有若干个发车时刻,每两个发车时刻间隔必须>=m,每个人的等待时长就是到最近一个发车时刻的时间累加,计算所有人等待时间最小值。......
  • Leetcode 力扣114. 二叉树展开为链表 (抖音号:708231408)
    给你二叉树的根结点 root ,请你将它展开为一个单链表:展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。展开后的单链表应该与二叉树 先序遍历 顺序相同。示例1:输入:root=[1,2,5,3,4,null,6]输出:[1,null,2......
  • 【数据结构】链式二叉树详解
    个人主页~链式二叉树基本内容~链式二叉树详解1、通过前序遍历的数组来构建二叉树2、二叉树的销毁3、二叉树节点个数4、二叉树叶子节点个数5、二叉树第k层节点个数6、二叉树查找7、前序遍历8、中序遍历9、后序遍历10、层序遍历与检查二叉树是否为完全二叉树Queue.hQue......
  • 代码随想录算法训练营第十四天|二叉树递归遍历、迭代遍历、统一迭代
    二叉树遍历二叉树主要有两种遍历方式:深度优先遍历:先往深走,遇到叶子节点再往回走。深度优先遍历又分:前序遍历(中、左、右)中序遍历(左、中、右)后序遍历(左、右、中)广度优先遍历:一层一层的去遍历。(后面讲)递归遍历递归三要素确定递归函数的参数和返回值:确定哪些参数是递......
  • 数据结构---树与二叉树
    个人介绍hellohello~,这里是code袁~......
  • Day47 代码随想录打卡|二叉树篇---最大二叉树
    题目(leecodeT654):给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建:创建一个根节点,其值为 nums 中的最大值。递归地在最大值 左边 的 子数组前缀上 构建左子树。递归地在最大值 右边 的 子数组后缀上 构建右子树。返回 nu......
  • 二叉树小结
    目录简介二叉树的种类在实际开发中评估二叉树的性能搜索二叉树代码实现二叉树堆的实现红黑树简介简介二叉树是一种特殊的树,每个节点最多有两个子节点,通常被称为左子节点和右子节点。它是计算机科学中的一种基础且重要的树形结构,被广泛应用在各种算法和数据结构中。二......
  • 【力扣】二叉树的最大深度
    给定一个二叉树root,返回其最大深度。二叉树的最大深度是指从根节点到最远叶子节点的最长路径上的节点数。示例1:输入:root=[3,9,20,null,null,15,7]输出:3示例2:输入:root=[1,null,2]输出:2层序遍历求深度流程层序遍历是对二叉树每一层进行遍历,我们定义一个......