劍指offer 76- 樹中兩個結(jié)點的最低公共祖先

給出一個二叉樹咬荷,輸入兩個樹節(jié)點路呜,求它們的最低公共祖先迷捧。

一個樹節(jié)點的祖先節(jié)點包括它本身。

注意:

輸入的二叉樹不為空胀葱;
輸入的兩個節(jié)點一定不為空党涕,且是二叉樹中的節(jié)點;

樣例

二叉樹[8, 12, 2, null, null, 6, 4, null, null, null, null]如下圖所示:
    8
   / \q
  12  2
     / \
    6   4

1. 如果輸入的樹節(jié)點為2和12巡社,則輸出的最低公共祖先為樹節(jié)點8膛堤。

2. 如果輸入的樹節(jié)點為2和6,則輸出的最低公共祖先為樹節(jié)點2晌该。

分析:
算法一:遞歸

若 rootrootroot 是 p,q 的 最近公共祖先 肥荔,則只可能為以下情況之一:

  • p 和 q在 root 的子樹中绿渣,且分列 root的 異側(cè)(即分別在左、右子樹中)燕耿;
  • p=root 中符,且 q 在 root 的左或右子樹中;
  • q=root 誉帅,且 p 在 root 的左或右子樹中淀散;

遞歸解析:

  • 終止條件:
    當越過葉節(jié)點,則直接返回 null蚜锨;
    當 root 等于 p,q 档插,則直接返回 root ;

  • 遞推過程:
    遞歸左子節(jié)點亚再,返回值記為 left 郭膛;
    遞歸右子節(jié)點,返回值記為 right 氛悬;

  • 返回值: 根據(jù) left 和 right 则剃,可展開為四種情況;
    當 left 和 right同時為空 :說明 root的左 / 右子樹中都不包含 p,q 如捅,返回 null 棍现;
    當 left 和 right 同時不為空 :說明 p,q 分列在 root 的 異側(cè) (分別在 左 / 右子樹),因此 root 為最近公共祖先镜遣,返回 root 轴咱;
    當 left 為空 ,right 不為空 :p,q 都不在 root 的左子樹中烈涮,直接返回 right 。具體可分為兩種情況:
    p,q 其中一個在 root的 右子樹 中窖剑,此時 right 指向 p(假設(shè)為 p )坚洽;
    p,q 兩節(jié)點都在 roo 的 右子樹 中,此時的 right 指向 最近公共祖先節(jié)點 西土;
    當 left不為空 讶舰, right 為空 :同理;

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(!root || root==p || root==q) return root;//遞歸終止條件
        auto left = lowestCommonAncestor(root->left, p, q);
        auto right = lowestCommonAncestor(root->right, p, q);
        if(left && right) return root;//兩個節(jié)點分別位于左子樹和右子樹
        if(!left) return right;//左子樹中兩個節(jié)點都找不到
        return left;//右子樹中兩個節(jié)點都找不到
    }
};

復(fù)雜度分析

  • 時間復(fù)雜度:O(N)需了,其中 NNN 是二叉樹的節(jié)點數(shù)跳昼。二叉樹的所有節(jié)點有且只會被訪問一次,因此時間復(fù)雜度為 O(N)肋乍。

  • 空間復(fù)雜度:O(N) 鹅颊,其中 NNN 是二叉樹的節(jié)點數(shù)。遞歸調(diào)用的棧深度取決于二叉樹的高度墓造,二叉樹最壞情況下為一條鏈堪伍,此時高度為 NNN锚烦,因此空間復(fù)雜度為 O(N)。

算法二:存儲父節(jié)點

我們可以用哈希表存儲所有節(jié)點的父節(jié)點帝雇,然后我們就可以利用節(jié)點的父節(jié)點信息從 p 結(jié)點開始不斷往上跳涮俄,并記錄已經(jīng)訪問過的節(jié)點,再從 q 節(jié)點開始不斷往上跳尸闸,如果碰到已經(jīng)訪問過的節(jié)點彻亲,那么這個節(jié)點就是我們要找的最近公共祖先。

從根節(jié)點開始遍歷整棵二叉樹吮廉,用哈希表記錄每個節(jié)點的父節(jié)點指針苞尝。
從 p 節(jié)點開始不斷往它的祖先移動,并用數(shù)據(jù)結(jié)構(gòu)記錄已經(jīng)訪問過的祖先節(jié)點茧痕。
同樣吼拥,我們再從 q 節(jié)點開始不斷往它的祖先移動优训,如果有祖先已經(jīng)被訪問過,即意味著這是 p 和 q 的深度最深的公共祖先。

復(fù)雜度分析

  • 時間復(fù)雜度:O(N)檀蹋,其中 N 是二叉樹的節(jié)點數(shù)。二叉樹的所有節(jié)點有且只會被訪問一次轻专,從 p 和 q 節(jié)點往上跳經(jīng)過的祖先節(jié)點個數(shù)不會超過 N蚓峦,因此總的時間復(fù)雜度為 O(N)。

  • 空間復(fù)雜度:O(N)气破,其中 N 是二叉樹的節(jié)點數(shù)聊浅。遞歸調(diào)用的棧深度取決于二叉樹的高度,二叉樹最壞情況下為一條鏈现使,此時高度為 N低匙,因此空間復(fù)雜度為 O(N),哈希表存儲每個節(jié)點的父節(jié)點也需要 O(N)的空間復(fù)雜度碳锈,因此最后總的空間復(fù)雜度為 O(N)顽冶。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    unordered_map<TreeNode*, TreeNode*> father;
    unordered_map<TreeNode*, bool> vis;
    void dfs(TreeNode* root) {
        if(root->left) father[root->left] = root, dfs(root->left);
        if(root->right) father[root->right] = root, dfs(root->right);
    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {   
        father[root] = nullptr;
        dfs(root);
        while(p) vis[p] = true, p = father[p];
        while(q) {
            if(vis[q]) return q;
            q = father[q];
        }
        return nullptr;
    }
};
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市售碳,隨后出現(xiàn)的幾起案子强重,更是在濱河造成了極大的恐慌,老刑警劉巖贸人,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件间景,死亡現(xiàn)場離奇詭異,居然都是意外死亡艺智,警方通過查閱死者的電腦和手機倘要,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來十拣,“玉大人碗誉,你說我怎么就攤上這事召嘶。” “怎么了哮缺?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵弄跌,是天一觀的道長。 經(jīng)常有香客問我尝苇,道長铛只,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任糠溜,我火速辦了婚禮淳玩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘非竿。我一直安慰自己蜕着,他們只是感情好,可當我...
    茶點故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布红柱。 她就那樣靜靜地躺著承匣,像睡著了一般。 火紅的嫁衣襯著肌膚如雪锤悄。 梳的紋絲不亂的頭發(fā)上韧骗,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天,我揣著相機與錄音零聚,去河邊找鬼袍暴。 笑死,一個胖子當著我的面吹牛隶症,可吹牛的內(nèi)容都是我干的政模。 我是一名探鬼主播,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼蚂会,長吁一口氣:“原來是場噩夢啊……” “哼淋样!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起颂龙,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎纽什,沒想到半個月后措嵌,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡芦缰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年企巢,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片让蕾。...
    茶點故事閱讀 40,015評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡浪规,死狀恐怖或听,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情笋婿,我是刑警寧澤誉裆,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站缸濒,受9級特大地震影響足丢,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜庇配,卻給世界環(huán)境...
    茶點故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一斩跌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧捞慌,春花似錦耀鸦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至锻霎,卻和暖如春著角,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背旋恼。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工吏口, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人冰更。 一個月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓产徊,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蜀细。 傳聞我的和親對象是個殘疾皇子舟铜,可洞房花燭夜當晚...
    茶點故事閱讀 44,969評論 2 355

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