[刷題]劍指offer之平衡二叉樹

題目

題目:輸入一棵二叉樹座柱,判斷該二叉樹是否是平衡二叉樹迷帜。

注:這個題思路很好,可以經(jīng)成矗看戏锹。

解法一

思路

一般來說,平衡二叉樹既是平衡的樹火诸,又是二分搜索樹锦针。但此題只要求判斷是不是平衡的。

判斷一棵樹是否是平衡的置蜀,就是判斷所有的節(jié)點是不是平衡的奈搜。

判斷一個節(jié)點是不是平衡的,就是判斷左右子節(jié)點的高度差是否<=1盯荤。

如果學(xué)過AVL樹馋吗,思路是一樣的,但是卻有一點不同秋秤,AVL樹的TreeNode結(jié)構(gòu)體(每個節(jié)點)中有一個成員表示高度宏粤,在每次插入節(jié)點的時候就會更新每個節(jié)點的高度,所以判斷是否平衡的時候可以直接判斷是否為平衡的灼卢。

而這個題的TreeNode結(jié)構(gòu)體如下所示:

struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};

這個結(jié)構(gòu)體并沒有保存高度信息绍哎,所以第一個想法是寫一個求高度的函數(shù),分別對左右子樹求高度鞋真,再看高度差受否滿足平衡二叉樹的要求崇堰。

求樹的高度可以使用遞歸法,樹的高度等于左右子樹高度的最大值再加上1(自身節(jié)點高度為1)灿巧,遞歸代碼如下:

int getHeight(TreeNode *node){
    if(node == NULL)
        return 0;
    return 1 + max(getHeight(node->left), getHeight(node->right));
}

判斷當(dāng)前節(jié)點是否平衡赶袄,就是計算左右子樹的高度差揽涮。

判斷當(dāng)前樹是不是平衡,就是判斷當(dāng)前節(jié)點饿肺、當(dāng)前節(jié)點的左子樹蒋困、當(dāng)前節(jié)點的右子樹是否平衡,還是個遞歸問題敬辣。

代碼

class Solution {
public:
    // 遞歸求高度
    int getHeight(TreeNode *node){
        if(node == NULL)
            return 0;
        return 1 + max(getHeight(node->left), getHeight(node->right));
    }
    //判斷該節(jié)點是否平衡
    bool IsBalanced(TreeNode *node){
        if(node == NULL)
            return true;
        if(abs(getHeight(node->left) - getHeight(node->right)) > 1)
            return false;
        return true;
    }
         
    bool IsBalanced_Solution(TreeNode* pRoot) {
        if(pRoot == NULL)
            return true;
        return IsBalanced(pRoot) && IsBalanced(pRoot->left) && IsBalanced(pRoot->right);
    }
};

代碼提交后雪标,成功過關(guān)。

解法二

思路

雖然成功的做出了這個題溉跃,但是總覺得有很別扭的地方村刨。

為了求判斷某個節(jié)點是不是平衡,需要求左右子樹的高度撰茎,判斷完該節(jié)點之后嵌牺,又需要判斷左子樹是不是平衡,這個時候又需要計算左子樹的左右子樹的高度龄糊,講道理逆粹,第一次遞歸求根節(jié)點的高度時,下面的節(jié)點的高度已經(jīng)被計算過了炫惩,但是卻沒有被記錄下來僻弹,導(dǎo)致白白遍歷了很多次。

借鑒動態(tài)規(guī)劃中的記憶化搜索他嚷,可以使用map<TreeNode*, int> mp來記錄每個節(jié)點的高度蹋绽,如果發(fā)現(xiàn)計算過,就直接返回記錄的值筋蓖。

這樣應(yīng)該能解決重復(fù)遞歸的問題卸耘,但是又增加了空間復(fù)雜度。

看了下別人的思路扭勉,豁然開朗鹊奖。原先的做法中,在求當(dāng)前節(jié)點的高度時涂炎,遞歸計算下面了所有節(jié)點的高度忠聚,但是卻沒有充分利用這些高度值。其實這個時候可以多做一件事情唱捣,判斷該節(jié)點是不是平衡的两蟀!如果不平衡,可以提前結(jié)束遞歸震缭。

代碼

class Solution {
public:
    int getHeight(TreeNode *node){
        if(node == NULL)
            return 0;
        int left = getHeight(node->left); //求左子樹的高度
        if(left == -1) return -1; //求左子樹的高度的時候發(fā)現(xiàn)了該節(jié)點不平衡
        int right = getHeight(node->right);
        if(right == -1) return -1;
        return abs(left - right) > 1 ? -1 : 1 + max(left, right); //求該節(jié)點的高度
    }
    bool IsBalanced_Solution(TreeNode* pRoot) {
        return getHeight(pRoot) != -1;
    }
};

思路還是有點繞赂毯,舉個栗子:

image.png

如上圖,遞歸的步驟是:

  1. 求節(jié)點1的高度時,遞歸到了葉子節(jié)點4党涕,左右節(jié)點的高度值都為0烦感,可以判斷出節(jié)點4是平衡的,所以求的節(jié)點4的高度值為1膛堤,并將這個高度值返回遞歸的上一層J秩ぁ!肥荔!
  2. 這時返回上一層绿渣,到了節(jié)點3。它得到到了左節(jié)點4的高度值1燕耿,繼續(xù)遞歸計算右節(jié)點的高度中符,得到高度值0,所以節(jié)點3滿足平衡條件誉帅,且自身的高度值為2淀散,又將這個高度值返回給上一層。
  3. 又返回了上一層堵第,到了節(jié)點2吧凉。它得到到了左節(jié)點3的高度值2隧出,繼續(xù)遞歸計算右節(jié)點的高度踏志,得到高度值0,這個時候就發(fā)現(xiàn)節(jié)點2不平衡的了胀瞪!沒有必要繼續(xù)再計算高度了针余,直接層層返回失敗就行了。由于返回值是int凄诞,所以設(shè)定返回-1就是失敗圆雁。這也就是為什么需要在得到高度后判斷是不是-1的原因。
  4. 最后只需要保證根節(jié)點的高度值不是-1就說明是這棵樹是平衡的了

總結(jié)

  • 遞歸是個大殺器帆谍,也難以利用伪朽,不要重復(fù)遞歸。

  • 遞歸說到底還是個棧汛蝙,只是利用了函數(shù)調(diào)用形成的棧烈涮。

我的segmentfault鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市窖剑,隨后出現(xiàn)的幾起案子坚洽,更是在濱河造成了極大的恐慌,老刑警劉巖西土,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件讶舰,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機跳昼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進店門般甲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人鹅颊,你說我怎么就攤上這事欣除。” “怎么了挪略?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵历帚,是天一觀的道長。 經(jīng)常有香客問我杠娱,道長挽牢,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任摊求,我火速辦了婚禮禽拔,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘室叉。我一直安慰自己睹栖,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布茧痕。 她就那樣靜靜地躺著野来,像睡著了一般。 火紅的嫁衣襯著肌膚如雪踪旷。 梳的紋絲不亂的頭發(fā)上曼氛,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天,我揣著相機與錄音令野,去河邊找鬼舀患。 笑死,一個胖子當(dāng)著我的面吹牛气破,可吹牛的內(nèi)容都是我干的聊浅。 我是一名探鬼主播,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼现使,長吁一口氣:“原來是場噩夢啊……” “哼低匙!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起朴下,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤努咐,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后殴胧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體渗稍,經(jīng)...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡佩迟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了竿屹。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片报强。...
    茶點故事閱讀 40,488評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖拱燃,靈堂內(nèi)的尸體忽然破棺而出秉溉,到底是詐尸還是另有隱情,我是刑警寧澤碗誉,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布召嘶,位于F島的核電站,受9級特大地震影響哮缺,放射性物質(zhì)發(fā)生泄漏弄跌。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一尝苇、第九天 我趴在偏房一處隱蔽的房頂上張望铛只。 院中可真熱鬧,春花似錦糠溜、人聲如沸淳玩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蜕着。三九已至,卻和暖如春汽馋,著一層夾襖步出監(jiān)牢的瞬間侮东,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工豹芯, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人驱敲。 一個月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓铁蹈,卻偏偏與公主長得像,于是被迫代替她去往敵國和親众眨。 傳聞我的和親對象是個殘疾皇子握牧,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,500評論 2 359

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