1. 程式人生 > >對稱二叉樹題解

對稱二叉樹題解

對稱二叉樹出處

這道題。。。。。。 本蒟蒻用暴力+輸入輸出優化+inline卡時間勉強AC 我的思路很簡單,從根開始依次往下遍歷,找最大值 注意題目描述:::

本題中約定,以節點 TT 為子樹根的一棵“子 樹”指的是:節點TT 和它的全部後代節點構成的二叉樹

本題中約定,以節點 TT 為子樹根的一棵“子 樹”指的是:節點TT 和它的全部後代節點構成的二叉樹

本題中約定,以節點 TT 為子樹根的一棵“子 樹”指的是:節點TT 和它的全部後代節點構成的二叉樹

所以只需要check一遍判斷就好了 我的程式碼很複雜 首先來看輸入輸出優化 輸入優化:

inline void
sc(int &x) {//讀入要改變x的值 x=0;int f=1;char s=getchar(); while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}//判斷正負 while(s>='0'&&s<='9'){x=x*10+s-48;s=getchar();}//讀入 x*=f;//稍微學過一點的都應該看得懂。。。 }

輸出優化:

inline void pr(int x) {
    if(x<0)putchar('-'),x=-x;//負數
    if(x>9)pr
(x/10);//用遞迴從前往後輸出 putchar(x%10+48);//輸出 }

以上兩段程式碼都是利用c++輸入輸出字元比數字快的原理 然後來看主程式:

int main() {
    sc(n);
    for(int i=1;i<=n;i++)
        sc(a[i].v);
    for(int i=1;i<=n;i++)
        sc(a[i].l),sc(a[i].r);
    dfs(1);
    pr(ans);
}

再來看dfs:

inline void dfs(int x) {//從根節點開始搜
    tot=3;
    if
(a[x].l==-1&&a[x].r==-1)//左右兒子都是-1 ans=max(ans,1),tot=3;//判斷,tot=3在程式碼後面解釋 else if(a[x].l!=-1&&a[x].r!=-1)//左右兒子都不是-1 if(check(a[x].l,a[x].r))//判斷是不是一棵對稱二叉樹 ans=max(ans,tot),tot=3; if(a[a[x].l].v!=a[a[x].r].v||a[x].l==-1||a[x].r==-1||!check(a[x].l,a[x].r)) {//在權值不等或一邊沒有或不是對稱二叉樹的情況下,要兩邊分別搜 if(a[x].l!=-1)//左邊有值搜左邊 dfs(a[x].l); tot=3; if(a[x].r!=-1)//右邊有值搜右邊 dfs(a[x].r); } tot=3; } /* 此處的inline可以減少函式呼叫的時間 */

tot=3是因為如果能進check的話就至少有三個。 其中根為一個,左右兒子有兩個 因為在check裡面沒打,所以就這樣了 接下來是check:

inline bool check(int x,int y) {//我判斷得很複雜,大家可以想想怎麼改進
    if(x==-1&&y==-1) return 1;
    else if(a[x].v!=a[y].v){tot=0;return 0;}
    else if((a[x].l==-1&&a[y].r!=-1)||(a[x].l!=-1&&a[y].r==-1)||(a[x].r==-1&&a[y].l!=-1)||(a[x].r!=-1&&a[y].l==-1)){tot=3;return 0;}
    else if(a[x].l!=-1&&a[y].r!=-1&&a[x].r!=-1&&a[y].l!=-1&&check(a[x].l,a[y].r)&&check(a[x].r,a[y].l)){tot+=4;return 1;}
    else if(a[x].l==-1&&a[y].r==-1&&a[x].r!=-1&&a[y].l!=-1&&check(a[x].r,a[y].l)){tot+=2;return 1;}
    else if(a[x].r==-1&&a[y].l==-1&&a[x].l!=-1&&a[y].r!=-1&&check(a[x].l,a[y].r)){tot+=2;return 1;}
    else if(a[x].l==-1&&a[x].r==-1&&a[y].l==-1&&a[y].r==-1)return 1;
    return check(a[x].l,a[y].r)&&check(a[x].r,a[y].l);
}
/*
第一個if是判斷如果沒有兒子就return
第一個else if是判斷兩邊權值不相等就不成立
第二個else if是判斷兒子對不對稱,不對稱就不成立
第三個else if是判斷兩個點都有兒子且兒子對稱,要加4個點
第四個else if是判斷x的左兒子和y的右兒子對不對稱,要加2個點
第五個else if是判斷x的右兒子和y的左兒子對不對稱,要加2個點
最後一個else if是判斷如果兩個點都沒有兒子,樹也是成立的
最後就是判斷
*/

是不是超複雜。。。。。。 下面是完整程式碼

#include<cstdio>
inline void sc(int &x) {
    x=0;int f=1;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-48;s=getchar();}
    x*=f;
}
inline void pr(int x) {
    if(x<0)putchar('-'),x=-x;
    if(x>9)pr(x/10);
    putchar(x%10+48);
}
inline int max(int x,int y) {
    return x>y?x:y;
}
struct node {
    int l,r,v;
}a[1000005];
int n,k,ans=1,tot=3;
inline bool check(int x,int y) {
    if(x==-1&&y==-1) return 1;
    else if(a[x].v!=a[y].v){tot=0;return 0;}
    else if((a[x].l==-1&&a[y].r!=-1)||(a[x].l!=-1&&a[y].r==-1)||(a[x].r==-1&&a[y].l!=-1)||(a[x].r!=-1&&a[y].l==-1)){tot=3;return 0;}
    else if(a[x].l!=-1&&a[y].r!=-1&&a[x].r!=-1&&a[y].l!=-1&&check(a[x].l,a[y].r)&&check(a[x].r,a[y].l)){tot+=4;return 1;}
    else if(a[x].l==-1&&a[y].r==-1&&a[x].r!=-1&&a[y].l!=-1&&check(a[x].r,a[y].l)){tot+=2;return 1;}
    else if(a[x].r==-1&&a[y].l==-1&&a[x].l!=-1&&a[y].r!=-1&&check(a[x].l,a[y].r)){tot+=2;return 1;}
    else if(a[x].l==-1&&a[x].r==-1&&a[y].l==-1&&a[y].r==-1)return 1;
    return check(a[x].l,a[y].r)&&check(a[x].r,a[y].l);
}
inline void dfs(int x) {
    tot=3;
    if(a[x].l==-1&&a[x].r==-1)
        ans=max(ans,1),tot=3;
    else if(a[x].l!=-1&&a[x].r!=-1)
        if(check(a[x].l,a[x].r))
            ans=max(ans,tot),tot=3;
    if(a[a[x].l].v!=a[a[x].r].v||a[x].l==-1||a[x].r==-1||!check(a[x].l,a[x].r)) {
        if(a[x].l!=-1)
            dfs(a[x].l);
        tot=3;
        if(a[x].r!=-1)
            dfs(a[x].r);
    }
    tot=3;
}
int main() {
    sc(n);
    for(int i=1;i<=n;i++)
        sc(a[i].v);
    for(int i=1;i<=n;i++)
        sc(a[i].l),sc(a[i].r);
    dfs(1);
    pr(ans);
}

大概用時670ms左右