zoukankan      html  css  js  c++  java
  • 递归基础_并查集思想_二叉树最大深度问题

    A: 二叉树的最大深度

    题目描述

    二叉树是指每个结点最多有两个子树的树结构,这两个子树通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。
    二叉树的结点层定义为:根结点的层定义为 1 ,根的孩子为第二层结点,依此类推;
    二叉树的深度定义为:树中最大的结点层。
    给定一颗以1号结点为根的二叉树,求它的最大深度。

    输入描述

    每组数据包含一颗二叉树,以如下形式给出:
    第一行为一个整数 n ( 1 ≤ n ≤ 20 ) ,表示二叉树的结点个数,结点编号为 1~n 。
    接下来直到输入数据末尾,每行为两个整数 x 和 y ,表示 x 和 y 之间有一条边,且 y 是 x 的儿子。
    输入保证是一颗合法的二叉树。

    输出描述

    输出一行,表示给定的二叉树的最大深度。

    样例输入

    3
    1 2
    2 3

    样例输出

    3

     思路:

    这个题一开始想着用模拟来解决,但是后来发现,这样做非常麻烦,因为你不知道怎么表示编号这件事情,链表不是顺序储存结构,

    访问是不能通过序列编号直接访问的,如果要这么做, 首先初始化链表到第n个,  然后,  每次都要从头节点找起,   然后找到对应编号重新移动节点, 非常难受

    而且给定的编号并不一定是规则的从上到下恰好从小到大(之前想用排序做但是WA了),除了第一个节点一定是1号之外 ,没有其他的限制

    但是,这题给的数据量是20,也就是说如果我每个结点都往上找到底不管怎样绝对不会超时或者爆炸,最大也就20*20=400,可以接受深搜,可以最长路径解决

    除了求图路径的办法,dp递推式,它的输入方法很神奇,x与y,很像并查集,

    复习一下,一般并查集:

    ——并查集——是利用数组下标 / 数组值嵌套—形成递归结构,从而实现

    比较全的想法整理:https://blog.csdn.net/yjr3426619/article/details/82315133,题集:https://www.cnblogs.com/cyanigence-oi/p/11774190.html

    init() find()union()为基础操作;模板如下:

     1 int fa[MAXN];
     2 inline void init(int n) {
     3     for (int i = 1; i <= n; ++i)
     4         fa[i] = i;
     5 }
     6 
     7 int find(int x) {
     8     if(fa[x] == x)
     9         return x;
    10     else
    11         return find(fa[x]);
    12 }
    13 
    14 inline void merge(int i, int j) {
    15     fa[find(i)] = find(j);
    16 }
    View Code

    如果有权值,则多设一个权值变量数组,合并操作

    不过,这题更简单,和一般并查集不一样的地方在于,我们知道这些节点一定是在同1块连通区域内的,而且本题对求路径长度的时间没有太多要求,

    因此,并查集中 init() find()union()的操作中,union可以被省略掉,

    那么简单利用数组下标和实际值嵌套,(更新路径长的并查集)实现递归,就可以解决了(以下为简易版本)

     1 #include <iostream>
     2 #include <cstring>
     3 #include <queue>
     4 #include <cstdio>
     5 #include <cmath>
     6 #include <map>
     7 #include <algorithm>
     8 typedef long long ll;
     9 using namespace std;
    10 int n;
    11 int len=0;
    12 #define o NULL
    13 //最深不会超过n,
    14 
    15 
    16 int a[25];
    17 int m=0;
    18 void f(int i) {
    19     if(a[i]==i) {
    20         len++;
    21         if(len>m)m=len;
    22         return;
    23     }
    24     if(a[i]!=i) {
    25         len++;
    26         f(a[i]);
    27     }
    28 
    29 }
    30 
    31 int main() {
    32     cin>>n;
    33     int x,y;
    34 
    35     for(int i=1; i<=n; i++) {
    36         a[i]=i;
    37     }
    38 
    39     while(cin>>x>>y) {
    40         a[y]=x;
    41         len=0; 
    42         f(y);
    43         //不用a[x]=y;
    44         //是因为父亲可以有多个儿子,但是儿子只有一个父亲,需要利用唯一关系
    45     }
    46     printf("%d
    ",m);
    47 }
    View Code

    复杂版本——带权并查集

    1 int find(int x) {
    2     if (x == pre[x])  return x;
    3     else {
    4         int root = find(pre[x]);     // 找到根节点
    5         sum[x] += sum[pre[x]];       // 权值合并,更新
    6         return pre[x] = root;        // 压缩路径
    7     }
    8 }
    9 //初始权值都为1,一个节点表示深度=1
    View Code

    这是升级版的———利用并查集求解路径长/ 深度的问题

    https://blog.csdn.net/qq_33204081/article/details/77189674

    进一步考虑到深度可以迭代实现递推的关系 len【儿子】=len【父亲】+1,更简单的做法: 

     1 #include <iostream>
     2 #include <cstring>
     3 #include <queue>
     4 #include <cstdio>
     5 #include <cmath>
     6 #include <map>
     7 #include <algorithm>
     8 typedef long long ll;
     9 using namespace std;
    10 int n;
    11 int len=0;
    12 #define o NULL
    13 //最深不会超过n,
    14 
    15 int m=0;
    16 int l[25];
    17 
    18 int main() {
    19     cin>>n;
    20     int x,y;
    21     for(int i=1; i<=n; i++) {
    22         l[i]=1;
    23     }
    24     while(cin>>x>>y) {
    25         l[y]=l[x]+1;
    26         if(m<l[y])m=l[y];
    27         //不用a[x]=y;
    28         //是因为父亲可以有多个儿子,但是儿子只有一个父亲,需要利用唯一关系
    29     }
    30     printf("%d
    ",m);
    31 }
    View Code

     也可以化成纯图论问题——求最长路径(待续更新)

    老实一点,可爱多了
  • 相关阅读:
    ES6-10笔记(class类)
    ES6-10笔记(let&const -- Array)
    小程序的表单提交
    小程序表单回显
    小程序template模板的使用和模板多数据传递
    微信小程序的初始配置
    babel 版本原因运行报错,解决办法
    webpack 和 webpack-cli 安装和使用中出现的问题
    jQuery中操作属性的方法attr与prop的区别
    javaScript 添加和移除class类名的几种方法
  • 原文地址:https://www.cnblogs.com/KID-yln/p/12531071.html
Copyright © 2011-2022 走看看