搜索練習題——對稱二叉樹

目錄ios

就在小蒟蒻正準備刷些\(bfs\)的題,忽然來了一位大佬,開始講一道藍色的\(bfs\)git


​ 這是一道很是很是很是厲害的題目,出自一個很是很是很是牛*的比賽。是的,就是 $NOIP_{普及組} $ (應該沒人看見右下角吧 \(\Omega \omega \Omega\)數組

對稱二叉樹函數

題目描述(本身口胡的):

給你一個二叉樹,讓你找出這棵樹的最大對稱二叉樹。什麼是對稱二叉樹呢???spa

對稱二叉樹就是一棵樹,以根節點向下畫一條垂線,根節點的左子樹和右子樹關於這條垂線對稱(只有權值是對稱的)。兩棵子樹不須要是對稱二叉樹。code

題目分析:

咱們能夠發現,若是存在對稱二叉樹,那麼在一層中必定存在兩個點,知足兩個點一個有左兒子一個有右兒子,或者都有兩個孩子。而且知足兩個點的權值都是相同的。根據這個結論咱們能夠寫出一個\(check\)函數。遞歸

​ 這就是\(wxl\)大佬給咱們講的大體思路,其餘的都在代碼裏了get

代碼實現:
#include<cstdio>
#include<iostream>
#include<algorithm>

using namespace std;

int n;
int son[1000050][2];
int val[1000050];
int size[1000050];

inline int read()//快速讀入 
{
    int F=1,ans=0;
    char c;
    c=getchar();
    while(!isdigit(c)){if(c=='-') F=-1; c=getchar();}
    while(isdigit(c)){ans=ans*10+c-'0'; c=getchar();}
    return ans*F;
}

void sum_size(int u)//用來預處理size數組 
{
    size[u]=1;
    if(son[u][0]!=-1)//若是有左兒子,就進行遞歸求出左兒子的sum值 
    {
        sum_size(son[u][0]);
        size[u]+=size[son[u][0]];
    }
    if(son[u][1]!=-1)//若是有右兒子,就進行遞歸求出右兒子的sum值 
    {
        sum_size(son[u][1]);
        size[u]+=size[son[u][1]];
    }
}

inline bool check(int u,int v)
{
    if(u==-1&&v==-1)//若是這是一個葉節點,就是正確的 
        return true;
    if(u!=-1&&v!=-1&&val[u]==val[v]&&check(son[u][0],son[v][1])&&check(son[u][1],son[v][0]))//若是這兩個點都知足對稱二叉樹的性質,就是正確的 
        return true;
    return false;
}

int main()
{
    n=read();
    for(int i=1;i<=n;++i)   val[i]=read();
    for(int i=1;i<=n;++i)
    {
        son[i][0]=read();
        son[i][1]=read();
    }
    sum_size(1);
    int ans=0;
    for(int i=1;i<=n;++i)
        if(check(son[i][0],son[i][1]))//循環求得每個對稱二叉樹 
            ans=max(ans,size[i]);//每次與找到的最大值進行比較 
    printf("%d",ans);
}

好像很水誒233(我是說這篇博客博客

相關文章
相關標籤/搜索