0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線(xiàn)課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

判斷對(duì)稱(chēng)二叉樹(shù)要比較的是哪兩個(gè)節(jié)點(diǎn)

算法與數(shù)據(jù)結(jié)構(gòu) ? 來(lái)源:代碼隨想錄 ? 作者:程序員Carl ? 2022-07-06 16:26 ? 次閱讀

101. 對(duì)稱(chēng)二叉樹(shù)

給定一個(gè)二叉樹(shù),檢查它是否是鏡像對(duì)稱(chēng)的。

c54bc0e8-fd04-11ec-ba43-dac502259ad0.png

思路

首先想清楚,判斷對(duì)稱(chēng)二叉樹(shù)要比較的是哪兩個(gè)節(jié)點(diǎn),要比較的可不是左右節(jié)點(diǎn)!

對(duì)于二叉樹(shù)是否對(duì)稱(chēng),要比較的是根節(jié)點(diǎn)的左子樹(shù)與右子樹(shù)是不是相互翻轉(zhuǎn)的,理解這一點(diǎn)就知道了其實(shí)我們要比較的是兩個(gè)樹(shù)(這兩個(gè)樹(shù)是根節(jié)點(diǎn)的左右子樹(shù)),所以在遞歸遍歷的過(guò)程中,也是要同時(shí)遍歷兩棵樹(shù)。

那么如果比較呢?

比較的是兩個(gè)子樹(shù)的里側(cè)和外側(cè)的元素是否相等。如圖所示:

c56013f4-fd04-11ec-ba43-dac502259ad0.png

那么遍歷的順序應(yīng)該是什么樣的呢?

本題遍歷只能是“后序遍歷”,因?yàn)槲覀円ㄟ^(guò)遞歸函數(shù)的返回值來(lái)判斷兩個(gè)子樹(shù)的內(nèi)側(cè)節(jié)點(diǎn)和外側(cè)節(jié)點(diǎn)是否相等。

正是因?yàn)橐闅v兩棵樹(shù)而且要比較內(nèi)側(cè)和外側(cè)節(jié)點(diǎn),所以準(zhǔn)確的來(lái)說(shuō)是一個(gè)樹(shù)的遍歷順序是左右中,一個(gè)樹(shù)的遍歷順序是右左中。

但都可以理解算是后序遍歷,盡管已經(jīng)不是嚴(yán)格上在一個(gè)樹(shù)上進(jìn)行遍歷的后序遍歷了。

其實(shí)后序也可以理解為是一種回溯,當(dāng)然這是題外話(huà),講回溯的時(shí)候會(huì)重點(diǎn)講的。

說(shuō)到這大家可能感覺(jué)我有點(diǎn)啰嗦,哪有這么多道理,上來(lái)就干就完事了。別急,我說(shuō)的這些在下面的代碼講解中都有身影。

那么我們先來(lái)看看遞歸法的代碼應(yīng)該怎么寫(xiě)。

遞歸法

遞歸三部曲

確定遞歸函數(shù)的參數(shù)和返回值

因?yàn)槲覀円容^的是根節(jié)點(diǎn)的兩個(gè)子樹(shù)是否是相互翻轉(zhuǎn)的,進(jìn)而判斷這個(gè)樹(shù)是不是對(duì)稱(chēng)樹(shù),所以要比較的是兩個(gè)樹(shù),參數(shù)自然也是左子樹(shù)節(jié)點(diǎn)和右子樹(shù)節(jié)點(diǎn)。

返回值自然是bool類(lèi)型。

代碼如下:

poYBAGLFR4yAPVqWAAAQuPTXo1A904.jpg

確定終止條件

要比較兩個(gè)節(jié)點(diǎn)數(shù)值相不相同,首先要把兩個(gè)節(jié)點(diǎn)為空的情況弄清楚!否則后面比較數(shù)值的時(shí)候就會(huì)操作空指針了。

節(jié)點(diǎn)為空的情況有:(注意我們比較的其實(shí)不是左孩子和右孩子,所以如下我稱(chēng)之為左節(jié)點(diǎn)右節(jié)點(diǎn))

左節(jié)點(diǎn)為空,右節(jié)點(diǎn)不為空,不對(duì)稱(chēng),return false

左不為空,右為空,不對(duì)稱(chēng) return false

左右都為空,對(duì)稱(chēng),返回true

此時(shí)已經(jīng)排除掉了節(jié)點(diǎn)為空的情況,那么剩下的就是左右節(jié)點(diǎn)不為空:

左右都不為空,比較節(jié)點(diǎn)數(shù)值,不相同就return false

此時(shí)左右節(jié)點(diǎn)不為空,且數(shù)值也不相同的情況我們也處理了。

代碼如下:

pYYBAGLFR6aAY2QmAABITjMqXUc205.jpg

注意上面最后一種情況,我沒(méi)有使用else,而是elseif, 因?yàn)槲覀儼岩陨锨闆r都排除之后,剩下的就是 左右節(jié)點(diǎn)都不為空,且數(shù)值相同的情況。

確定單層遞歸的邏輯

此時(shí)才進(jìn)入單層遞歸的邏輯,單層遞歸的邏輯就是處理 右節(jié)點(diǎn)都不為空,且數(shù)值相同的情況。

比較二叉樹(shù)外側(cè)是否對(duì)稱(chēng):傳入的是左節(jié)點(diǎn)的左孩子,右節(jié)點(diǎn)的右孩子。

比較內(nèi)測(cè)是否對(duì)稱(chēng),傳入左節(jié)點(diǎn)的右孩子,右節(jié)點(diǎn)的左孩子。

如果左右都對(duì)稱(chēng)就返回true ,有一側(cè)不對(duì)稱(chēng)就返回false 。

代碼如下:

poYBAGLFR8GAek6NAABGcSkJYew381.jpg

如上代碼中,我們可以看出使用的遍歷方式,左子樹(shù)左右中,右子樹(shù)右左中,所以我把這個(gè)遍歷順序也稱(chēng)之為“后序遍歷”(盡管不是嚴(yán)格的后序遍歷)。

最后遞歸的C++整體代碼如下:

poYBAGLFR9-AKoDSAADhGvnLjmI811.jpg

我給出的代碼并不簡(jiǎn)潔,但是把每一步判斷的邏輯都清楚的描繪出來(lái)了。

如果上來(lái)就看網(wǎng)上各種簡(jiǎn)潔的代碼,看起來(lái)真的很簡(jiǎn)單,但是很多邏輯都掩蓋掉了,而題解可能也沒(méi)有把掩蓋掉的邏輯說(shuō)清楚。

盲目的照著抄,結(jié)果就是:發(fā)現(xiàn)這是一道“簡(jiǎn)單題”,稀里糊涂的就過(guò)了,但是真正的每一步判斷邏輯未必想到清楚。

當(dāng)然我可以把如上代碼整理如下:

pYYBAGLFR_WAakX3AACMdaxuhp0814.jpg

這個(gè)代碼就很簡(jiǎn)潔了,但隱藏了很多邏輯,條理不清晰,而且遞歸三部曲,在這里完全體現(xiàn)不出來(lái)。

所以建議大家做題的時(shí)候,一定要想清楚邏輯,每一步做什么。把道題目所有情況想到位,相應(yīng)的代碼寫(xiě)出來(lái)之后,再去追求簡(jiǎn)潔代碼的效果。

迭代法

這道題目我們也可以使用迭代法,但要注意,這里的迭代法可不是前中后序的迭代寫(xiě)法,因?yàn)楸绢}的本質(zhì)是判斷兩個(gè)樹(shù)是否是相互翻轉(zhuǎn)的,其實(shí)已經(jīng)不是所謂二叉樹(shù)遍歷的前中后序的關(guān)系了。

這里我們可以使用隊(duì)列來(lái)比較兩個(gè)樹(shù)(根節(jié)點(diǎn)的左右子樹(shù))是否相互翻轉(zhuǎn),(注意這不是層序遍歷)

使用隊(duì)列

通過(guò)隊(duì)列來(lái)判斷根節(jié)點(diǎn)的左子樹(shù)和右子樹(shù)的內(nèi)側(cè)和外側(cè)是否相等,如動(dòng)畫(huà)所示:

c575382e-fd04-11ec-ba43-dac502259ad0.gif

如下的條件判斷和遞歸的邏輯是一樣的。

代碼如下:

poYBAGLFSBGAefZLAADwW9iQ3gw401.jpg

使用棧

細(xì)心的話(huà),其實(shí)可以發(fā)現(xiàn),這個(gè)迭代法,其實(shí)是把左右兩個(gè)子樹(shù)要比較的元素順序放進(jìn)一個(gè)容器,然后成對(duì)成對(duì)的取出來(lái)進(jìn)行比較,那么其實(shí)使用棧也是可以的。

只要把隊(duì)列原封不動(dòng)的改成棧就可以了,我下面也給出了代碼。

poYBAGLFSCiAYppNAACr8ADruEI559.jpg

總結(jié)

這次我們又深度剖析了一道二叉樹(shù)的“簡(jiǎn)單題”,大家會(huì)發(fā)現(xiàn),真正的把題目搞清楚其實(shí)并不簡(jiǎn)單,leetcode上accept了和真正掌握了還是有距離的。

我們介紹了遞歸法和迭代法,遞歸依然通過(guò)遞歸三部曲來(lái)解決了這道題目,如果只看精簡(jiǎn)的代碼根本看不出來(lái)遞歸三部曲是如果解題的。

在迭代法中我們使用了隊(duì)列,需要注意的是這不是層序遍歷,而且僅僅通過(guò)一個(gè)容器來(lái)成對(duì)的存放我們要比較的元素,知道這一本質(zhì)之后就發(fā)現(xiàn),用隊(duì)列,用棧,甚至用數(shù)組,都是可以的。

如果已經(jīng)做過(guò)這道題目的同學(xué),讀完文章可以再去看看這道題目,思考一下,會(huì)有不一樣的發(fā)現(xiàn)!

相關(guān)題目推薦

100.相同的樹(shù)

572.另一個(gè)樹(shù)的子樹(shù)

其他語(yǔ)言版本

Java

pYYBAGLFSF2ADY9uAACr4DprcZA332.jpg

poYBAGLFSG6AKXUhAAEOFGGfMWU626.jpg

poYBAGLFSHaAackKAAD6VGhZVno319.jpg

Python

遞歸法:

poYBAGLFSIyASH4MAADTVj4n-so737.jpg

迭代法:使用隊(duì)列

poYBAGLFSKCAcVZxAADvrTwwIis108.jpg

迭代法:使用棧

poYBAGLFSLaAWPsjAACc4bGIAhg462.jpg





審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • JAVA
    +關(guān)注

    關(guān)注

    19

    文章

    2947

    瀏覽量

    104373
  • python
    +關(guān)注

    關(guān)注

    54

    文章

    4759

    瀏覽量

    84295

原文標(biāo)題:判斷二叉樹(shù)是否對(duì)稱(chēng)

文章出處:【微信號(hào):TheAlgorithm,微信公眾號(hào):算法與數(shù)據(jù)結(jié)構(gòu)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    什么是默克爾樹(shù)(Merkle Tree)?如何計(jì)算默克爾根?

    01 默克爾樹(shù)的概念 默克爾樹(shù)(Merkle Tree)是一種特殊的二叉樹(shù),它的每個(gè)節(jié)點(diǎn)都存儲(chǔ)了一個(gè)數(shù)據(jù)塊的哈希值。哈希值是一種可以將任意長(zhǎng)
    的頭像 發(fā)表于 09-30 18:22 ?272次閱讀
    什么是默克爾<b class='flag-5'>樹(shù)</b>(Merkle Tree)?如何計(jì)算默克爾根?

    兩個(gè)極管反向串聯(lián)是什么元件

    兩個(gè)極管反向串聯(lián)是一種常見(jiàn)的電路元件,通常被稱(chēng)為雙向極管或雙向穩(wěn)壓極管。這種元件具有獨(dú)特的電氣特性,可以在正向和反向電壓下工作,廣泛應(yīng)用于各種電子電路中。 一、雙向
    的頭像 發(fā)表于 08-16 16:05 ?1565次閱讀

    極管的伏安特性分為兩個(gè)部分?

    極管是一種半導(dǎo)體器件,具有單向?qū)щ娦?。其伏安特性是描?b class='flag-5'>二極管在不同電壓下電流變化的曲線(xiàn)。極管的伏安特性可以分為兩個(gè)部分:正向特性和反向特性。 正向特性 正向特性是指
    的頭像 發(fā)表于 08-16 11:16 ?460次閱讀

    觸發(fā)器的兩個(gè)穩(wěn)定狀態(tài)分別是什么

    觸發(fā)器作為數(shù)字電路中的基本邏輯單元,具有兩個(gè)穩(wěn)定狀態(tài),這兩個(gè)狀態(tài)通常用于表示進(jìn)制數(shù)碼中的0和1。
    的頭像 發(fā)表于 08-12 11:01 ?314次閱讀

    使用比較器TLV7041判斷兩個(gè)信號(hào)的大小,但輸出未按預(yù)期進(jìn)行是怎么回事?

    我現(xiàn)在需要使用比較判斷兩個(gè)信號(hào)的大小,但輸出未按預(yù)期進(jìn)行(不能比較者大小)。如下圖,U17是比較
    發(fā)表于 08-12 08:20

    節(jié)點(diǎn)電壓法流入節(jié)點(diǎn)電流怎么判斷正負(fù)

    的電壓。在分析過(guò)程中,我們需要判斷流入節(jié)點(diǎn)的電流的正負(fù)。 節(jié)點(diǎn)電壓法概述 在節(jié)點(diǎn)電壓法中,我們首先選擇一個(gè)參考
    的頭像 發(fā)表于 08-06 17:24 ?1084次閱讀

    運(yùn)放做比較兩個(gè)輸入相等怎么辦

    比較器是運(yùn)放的一種常見(jiàn)應(yīng)用,主要用于比較兩個(gè)模擬信號(hào)的大小。 當(dāng)運(yùn)放用作比較器時(shí),其兩個(gè)輸入端分別為非反向輸入端(+)和反向輸入端(-)。
    的頭像 發(fā)表于 07-10 10:34 ?643次閱讀

    交流元繼電器有兩個(gè)線(xiàn)圈

    交流元繼電器是一種常見(jiàn)的電氣元件,廣泛應(yīng)用于各種電氣控制系統(tǒng)中。它主要由兩個(gè)線(xiàn)圈組成,這兩個(gè)線(xiàn)圈分別是線(xiàn)圈1和線(xiàn)圈2。下面我們將詳細(xì)介紹這兩個(gè)線(xiàn)圈的特點(diǎn)、工作原理以及在實(shí)際應(yīng)用中的注
    的頭像 發(fā)表于 06-29 09:43 ?458次閱讀

    對(duì)稱(chēng)短路有哪些 對(duì)稱(chēng)短路的形式有四種

    對(duì)稱(chēng)短路有哪些 對(duì)稱(chēng)短路的形式有四種? 對(duì)稱(chēng)短路是指電路中的兩個(gè)電路元件或?qū)Ь€(xiàn)之間有相同的電位差,從而形成電流的直接流動(dòng)。
    的頭像 發(fā)表于 02-18 10:17 ?2051次閱讀

    Psoc4 4247LQI483如何判斷產(chǎn)生的中斷是由兩個(gè)比較器中的哪一個(gè)輸出的上升沿觸發(fā)的呢?

    LPcomparator的中斷使能時(shí),提示我們使用global signal reference并且選擇LPCompInt。那么,我們?nèi)绾?b class='flag-5'>判斷這個(gè)產(chǎn)生的中斷是由兩個(gè)比較器中的哪一個(gè)輸出
    發(fā)表于 02-18 08:26

    堆的實(shí)現(xiàn)思路

    什么是堆? 堆是一種 基于樹(shù)結(jié)構(gòu)的數(shù)據(jù)結(jié)構(gòu),它是一棵二叉樹(shù) ,具有以下兩個(gè)特點(diǎn): 堆是一個(gè)完全二叉樹(shù),即除了最后一層,其他層都是滿(mǎn)的,最后一層從左到右填滿(mǎn)。 堆中每個(gè)
    的頭像 發(fā)表于 11-24 16:02 ?368次閱讀
    堆的實(shí)現(xiàn)思路

    樹(shù)二叉樹(shù)的定義

    樹(shù)型結(jié)構(gòu) 是一類(lèi)重要的 非線(xiàn)性數(shù)據(jù)結(jié)構(gòu) ,其中以樹(shù)二叉樹(shù)最為常用,直觀來(lái)看,樹(shù)是以分支關(guān)系定義的層次結(jié)構(gòu)。樹(shù)型結(jié)構(gòu)在客觀世界中廣泛存在,比
    的頭像 發(fā)表于 11-24 15:57 ?1166次閱讀
    <b class='flag-5'>樹(shù)</b>與<b class='flag-5'>二叉樹(shù)</b>的定義

    什么情況下需要布隆過(guò)濾器

    , gmail等郵箱垃圾郵件過(guò)濾功能 這幾個(gè)例子有一個(gè)共同的特點(diǎn):如何判斷個(gè)元素是否存在一個(gè)集合中? 常規(guī)思路 數(shù)組 鏈表 樹(shù)、平衡
    的頭像 發(fā)表于 11-11 11:37 ?602次閱讀
    什么情況下需要布隆過(guò)濾器

    為什么MySQL索引要用B+tree?

    紅黑樹(shù)是一種特化的 AVL樹(shù)(平衡二叉樹(shù)),都是在進(jìn)行插入和刪除操作時(shí)通過(guò)特定操作保持二叉查找樹(shù)的平衡; 若一棵
    發(fā)表于 10-30 14:41 ?195次閱讀

    芯片外圍電路如何比較兩個(gè)不同阻值的大小呢?

    在一些芯片外圍電路中有時(shí)需要引腳接不同的阻值以對(duì)應(yīng)不同的功能或狀態(tài),這往往需要比較電阻阻值的大小,類(lèi)似于電壓比較
    的頭像 發(fā)表于 10-29 17:21 ?1128次閱讀
    芯片外圍電路如何<b class='flag-5'>比較</b><b class='flag-5'>兩個(gè)</b>不同阻值的大小呢?