對(duì)稱的二叉樹

題目描述

請(qǐng)實(shí)現(xiàn)一個(gè)函數(shù)尘盼,用來判斷一顆二叉樹是不是對(duì)稱的统舀。注意,如果一個(gè)二叉樹同此二叉樹的鏡像是同樣的澄港,定義其為對(duì)稱的椒涯。

image

解法一:

? ? 我們知道中序遍歷是先遍歷左子節(jié)點(diǎn),再遍歷根節(jié)點(diǎn)回梧,最后遍歷右子節(jié)點(diǎn)废岂。如果一顆二叉樹是對(duì)稱的,則使用中序遍歷的對(duì)稱遍歷方法得到的結(jié)果應(yīng)該與中序遍歷的結(jié)果相同漂辐。所謂對(duì)稱遍歷方法泪喊,即先遍歷右子節(jié)點(diǎn),再遍歷根節(jié)點(diǎn)髓涯,最后遍歷左子節(jié)點(diǎn)袒啼。

? ? 但是這種方法遇到第三種二叉樹時(shí),中序遍歷結(jié)果為777777纬纪,中序遍歷的對(duì)稱遍歷結(jié)果也為777777蚓再。要解決這個(gè)問題,只需要將空節(jié)點(diǎn)考慮進(jìn)去就可以了包各。

public class Solution {
    ArrayList<TreeNode> preOrder = new ArrayList<TreeNode>();
    ArrayList<TreeNode> afterOrder = new ArrayList<TreeNode>();
    boolean isSymmetrical(TreeNode pRoot) {
        getPreOrder(pRoot);
        getAfterOrder(pRoot);
        //比較中序遍歷和中序遍歷的對(duì)稱遍歷
        for(int i = 0; i < preOrder.size(); i++) {
            if(preOrder.get(i) == null && afterOrder.get(i) != null) {
                return false;
            }
            if(preOrder.get(i) != null && afterOrder.get(i) == null){
                return false;
            }
            if(preOrder.get(i) == null && afterOrder.get(i) == null) {
                continue;
            }
            if(preOrder.get(i).val != afterOrder.get(i).val) {
                return false;
            }
        }
        return true;
    }
    //獲得中序遍歷
    public void getPreOrder(TreeNode pRoot) {
        if(pRoot == null) {
            preOrder.add(pRoot);
            return ;
        }
        if(pRoot.left == null && pRoot.right == null) {
            preOrder.add(pRoot);
        }
        else {
            getPreOrder(pRoot.left);
            preOrder.add(pRoot);
            getPreOrder(pRoot.right);
        }
    }
    //獲得中序遍歷的對(duì)稱遍歷
    public void getAfterOrder(TreeNode pRoot) {
        if(pRoot == null) {
            afterOrder.add(pRoot);
            return ;
        }
        if(pRoot.left == null && pRoot.right == null) {
            afterOrder.add(pRoot);
        }
        else {
            getAfterOrder(pRoot.right);
            afterOrder.add(pRoot);
            getAfterOrder(pRoot.left);
        }
    }
}

解法二:

在解法一中將全部的遍歷序列進(jìn)行了保存摘仅,之后再比較遍歷序列∥食空間和時(shí)間效率都不是很好娃属。可以在遍歷二叉樹的過程中進(jìn)行比較护姆,設(shè)置兩個(gè)指針執(zhí)行不同的遍歷方法矾端,比較兩個(gè)指針的值。

下列代碼使用了前序遍歷和前序遍歷的對(duì)稱遍歷卵皂。

public class Solution {
    boolean isSymmetrical(TreeNode pRoot) {
        return checker(pRoot, pRoot);
    }
    public boolean checker(TreeNode pRoot1, TreeNode pRoot2) {
        if(pRoot1 == null && pRoot2 != null) {
            return false;
        }
        if(pRoot1 != null && pRoot2 == null) {
            return false;
        }
        if(pRoot1 == null && pRoot2 == null) {
            return true;
        }
        if(pRoot1.val != pRoot2.val) {
            return false;
        }
        return checker(pRoot1.left, pRoot2.right) && checker(pRoot1.right, pRoot2.left);
    }
}

解法三:

我們?nèi)斯とシ直嬉豢脴涫欠駷閷?duì)稱二叉樹時(shí)秩铆,不是使用各種遍歷,而是直觀地自上而下來判斷每一行是否為對(duì)稱的灯变。于是我們也可以按層來遍歷二叉樹殴玛,再分析每一層是否對(duì)稱。同樣地添祸,對(duì)于第三種二叉樹的情況滚粟,需要考慮空節(jié)點(diǎn)。

public class Solution {
    ArrayList<ArrayList<TreeNode>> list = new ArrayList<ArrayList<TreeNode>>();
    boolean isSymmetrical(TreeNode pRoot) {
        ArrayList<TreeNode> firstLine = new ArrayList<TreeNode>();
        firstLine.add(pRoot);
        list.add(firstLine);
        if(pRoot == null) {
            return true;
        }
                //按層遍歷二叉樹
        for(int i = 0; i < list.size(); i++) {
            ArrayList<TreeNode> currentLine = list.get(i);
            ArrayList<TreeNode> newLine = new ArrayList<TreeNode>();
            for(int j = 0; j < currentLine.size(); j++) {
                TreeNode currentNode = currentLine.get(j);
                if(currentNode != null && !(currentNode.left == null && currentNode.right == null)) {
                    newLine.add(currentNode.left);
                    newLine.add(currentNode.right);
                }
            }
            if(newLine.size() != 0) {
                list.add(newLine);
            }
        }
        return check(list);
    }
        //按層判斷是否對(duì)稱
    public boolean check(ArrayList<ArrayList<TreeNode>> list) {
        for(int i = 0; i < list.size(); i++) {
            ArrayList<TreeNode> currentLine = list.get(i);
            int start = 0;
            int end = currentLine.size() - 1;
            while(start < end) {
                if(currentLine.get(start) == null && currentLine.get(end) != null) {
                    return false;
                }
                if(currentLine.get(start) != null && currentLine.get(end) == null) {
                    return false;
                }
                if(currentLine.get(start) != null && currentLine.get(end) != null) {
                    if(currentLine.get(start).val != currentLine.get(end).val) {
                        return false;
                    }
                }
                start++;
                end--;
            }
        }
        return true;
    }
}

由于每一層的數(shù)量不定刃泌,按層遍歷時(shí)如果將所有的結(jié)果都放在一起坦刀,分析每一層是否對(duì)稱時(shí)很難將每一層分開愧沟,于是我們采用ArrayList<ArrayList<TreeNode>>來存儲(chǔ)每一層。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末鲤遥,一起剝皮案震驚了整個(gè)濱河市沐寺,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌盖奈,老刑警劉巖混坞,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異钢坦,居然都是意外死亡究孕,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門爹凹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來厨诸,“玉大人,你說我怎么就攤上這事禾酱∥⒊辏” “怎么了?”我有些...
    開封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵颤陶,是天一觀的道長颗管。 經(jīng)常有香客問我,道長滓走,這世上最難降的妖魔是什么垦江? 我笑而不...
    開封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮搅方,結(jié)果婚禮上比吭,老公的妹妹穿的比我還像新娘。我一直安慰自己姨涡,他們只是感情好衩藤,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著绣溜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪娄蔼。 梳的紋絲不亂的頭發(fā)上怖喻,一...
    開封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音岁诉,去河邊找鬼锚沸。 笑死,一個(gè)胖子當(dāng)著我的面吹牛涕癣,可吹牛的內(nèi)容都是我干的哗蜈。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼距潘!你這毒婦竟也來了炼列?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤音比,失蹤者是張志新(化名)和其女友劉穎俭尖,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體洞翩,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡稽犁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了骚亿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片已亥。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖来屠,靈堂內(nèi)的尸體忽然破棺而出虑椎,到底是詐尸還是另有隱情,我是刑警寧澤的妖,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布绣檬,位于F島的核電站,受9級(jí)特大地震影響嫂粟,放射性物質(zhì)發(fā)生泄漏娇未。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一星虹、第九天 我趴在偏房一處隱蔽的房頂上張望零抬。 院中可真熱鬧,春花似錦宽涌、人聲如沸平夜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽忽妒。三九已至,卻和暖如春兼贸,著一層夾襖步出監(jiān)牢的瞬間段直,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國打工溶诞, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鸯檬,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓螺垢,卻偏偏與公主長得像喧务,于是被迫代替她去往敵國和親赖歌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 樹的概述 樹是一種非常常用的數(shù)據(jù)結(jié)構(gòu)功茴,樹與前面介紹的線性表庐冯,棧,隊(duì)列等線性結(jié)構(gòu)不同痊土,樹是一種非線性結(jié)構(gòu) 1.樹的定...
    Jack921閱讀 4,434評(píng)論 1 31
  • 本系列導(dǎo)航:劍指offer(第二版)java實(shí)現(xiàn)導(dǎo)航帖 面試題28:對(duì)稱的二叉樹 題目要求:判斷一棵二叉樹是不是對(duì)...
    ryderchan閱讀 1,001評(píng)論 0 0
  • 題目描述 請(qǐng)實(shí)現(xiàn)一個(gè)函數(shù)肄扎,用來判斷一顆二叉樹是不是對(duì)稱的。注意赁酝,如果一個(gè)二叉樹同此二叉樹的鏡像是同樣的犯祠,定義其為對(duì)...
    Gxxx_xx閱讀 695評(píng)論 1 0
  • 題干 請(qǐng)實(shí)現(xiàn)一個(gè)函數(shù),用來判斷一棵二叉樹是不是對(duì)稱的酌呆。如果一棵二叉樹和它的鏡像一樣衡载,那么它就是對(duì)稱的。例如在下圖的...
    懶人成長閱讀 228評(píng)論 0 0
  • 五月二號(hào)下午四點(diǎn)四十八的火車票出來隙袁,出來之前去兩個(gè)單位查詢工作所需痰娱,但都沒有獲得任何有效結(jié)果,對(duì)于自己而言...
    鄭律文記閱讀 614評(píng)論 0 0