LeetCode - 236. 二叉樹(shù)的最近公共祖先 Java & Swift

給定一個(gè)二叉樹(shù), 找到該樹(shù)中兩個(gè)指定節(jié)點(diǎn)的最近公共祖先嘶朱。

百度百科中最近公共祖先的定義為:“對(duì)于有根樹(shù) T 的兩個(gè)結(jié)點(diǎn) p怕篷、q移必,最近公共祖先表示為一個(gè)結(jié)點(diǎn) x,滿足 x 是 p忧设、q 的祖先且 x 的深度盡可能大(一個(gè)節(jié)點(diǎn)也可以是它自己的祖先)∩缤矗”

例如见转,給定如下二叉樹(shù): root = [3,5,1,6,2,0,8,null,null,7,4]

示例 1:

輸入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
輸出: 3
解釋: 節(jié)點(diǎn) 5 和節(jié)點(diǎn) 1 的最近公共祖先是節(jié)點(diǎn) 3。
示例 2:

輸入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
輸出: 5
解釋: 節(jié)點(diǎn) 5 和節(jié)點(diǎn) 4 的最近公共祖先是節(jié)點(diǎn) 5蒜哀。因?yàn)楦鶕?jù)定義最近公共祖先節(jié)點(diǎn)可以為節(jié)點(diǎn)本身斩箫。

說(shuō)明:

所有節(jié)點(diǎn)的值都是唯一的。
p撵儿、q 為不同節(jié)點(diǎn)且均存在于給定的二叉樹(shù)中乘客。

來(lái)源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree
著作權(quán)歸領(lǐng)扣網(wǎng)絡(luò)所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系官方授權(quán)淀歇,非商業(yè)轉(zhuǎn)載請(qǐng)注明出處易核。

算法

Java
/**
     * 遞歸
     * 參考題解:鏈接:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/solution/236-er-cha-shu-de-zui-jin-gong-gong-zu-xian-hou-xu/
     * 若 root 是 p, q 的 最近公共祖先 饵史,則只可能為以下情況之一:
        p 和 q 在 root 的子樹(shù)中,且分列 root 的 異側(cè)(即分別在左胜榔、右子樹(shù)中)胳喷;
        p = root,且 q 在 root 的左或右子樹(shù)中夭织;
        q = root 吭露,且 p 在 root 的左或右子樹(shù)中;
     */
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        // root 為null 或者 p尊惰、q 是 root
        if (root == null || q == root || p == root) {
            return root;
        }
        TreeNode left = lowestCommonAncestor(root.left, p, q);
        TreeNode right = lowestCommonAncestor(root.right, p, q);
        // 左邊為null奴饮,共同祖先節(jié)點(diǎn)在右側(cè)
        if (left == null) {
            return right;
        }
        // 右邊為null纬向,共同祖先節(jié)點(diǎn)在左側(cè)
        if (right == null) {
            return left;
        }
        return root;
    }
    Map<Integer, TreeNode> map = new HashMap<>();
    Set<Integer> visited = new HashSet<>();

    /**
     * 參考題解:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/solution/er-cha-shu-de-zui-jin-gong-gong-zu-xian-by-leetc-2/
     * 從上向下遍歷所有的父節(jié)點(diǎn),將父節(jié)點(diǎn)保存到哈希表中
     * 從p節(jié)點(diǎn)向上查詢它的父節(jié)點(diǎn)投剥,保存到臨時(shí)數(shù)組中师脂,判斷臨時(shí)數(shù)組中是否包含q節(jié)點(diǎn)
     */
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        dfs(root);
        // 從p節(jié)點(diǎn)向上訪問(wèn)所有的父節(jié)點(diǎn)
        while (p != null) {
            visited.add(p.val);
            p = map.get(p.val);
        }
        // 從q節(jié)點(diǎn)向上訪問(wèn)所有的父節(jié)點(diǎn)
        while (q != null) {
            // 判斷p的父節(jié)點(diǎn)是否包含q的父節(jié)點(diǎn)
            if (visited.contains(q.val)) {
                return q;
            }
            q = map.get(q.val);
        }
        return null;
    }
    /**
     * 遞歸遍歷父節(jié)點(diǎn)
     * @param node
     */
    public void dfs(TreeNode node) {
        if (node.left != null) {
            map.put(node.left.val, node);
            dfs(node.left);
        }
        if (node.right != null) {
            map.put(node.right.val, node);
            dfs(node.right);
        }
    }
swift
  • 遞歸
/**
     遞歸
     */
    func lowestCommonAncestor(_ root: TreeNode?, _ p: TreeNode?, _ q: TreeNode?) -> TreeNode? {
        // 如果root為nil余爆、p 為 root织盼、q為root,則共同祖先節(jié)點(diǎn)為root
        if root == nil || p?.val == root?.val || q?.val == root?.val {
            return root
        }
        // 遞歸左右子樹(shù)
        let left = lowestCommonAncestor(root?.left, p, q)
        let right = lowestCommonAncestor(root?.right, p, q)
        // 左子樹(shù)為nil阀蒂,則祖先節(jié)點(diǎn)在右子樹(shù)中
        if left == nil {
            return right
        }
        // 右子樹(shù)為nil啄育,則祖先節(jié)點(diǎn)在左子樹(shù)中
        if right == nil {
            return left
        }
        return root
    }
  • 存儲(chǔ)父節(jié)點(diǎn)

class Solution {
    
    // 父節(jié)點(diǎn)字典
    var dict = [Int: TreeNode]()
    // 已訪問(wèn)節(jié)點(diǎn)數(shù)組
    var visited = [TreeNode]()
    
    /**
     從上到下遍歷父節(jié)點(diǎn)酌心,保存所有的父節(jié)點(diǎn)到字典中
     */
    func lowestCommonAncestor(_ root: TreeNode?, _ p: TreeNode?, _ q: TreeNode?) -> TreeNode? {
        dfs(root)
        // 從p節(jié)點(diǎn)想上訪問(wèn)其所有的父節(jié)點(diǎn),保存到已訪問(wèn)數(shù)組中
        var p = p
        while p != nil {
            visited.append(p!)
            // 移動(dòng)到p的父節(jié)點(diǎn)
            p = dict[p!.val]
        }
        var q = q
        while q != nil {
            if visited.contains(where: { (node) -> Bool in
                return q!.val == node.val
            }) {
                return q
            }
            q = dict[q!.val]
        }
        return nil
    }
    
    func dfs(_ node: TreeNode?) {
        if node?.left != nil {
            dict[node!.left!.val] = node
            dfs(node?.left)
        }
        if node?.right != nil {
            dict[node!.right!.val] = node
            dfs(node?.right)
        }
    }
}

GitHub:https://github.com/huxq-coder/LeetCode
歡迎star

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末挑豌,一起剝皮案震驚了整個(gè)濱河市安券,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌氓英,老刑警劉巖侯勉,帶你破解...
    沈念sama閱讀 216,591評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異铝阐,居然都是意外死亡址貌,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)徘键,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)练对,“玉大人,你說(shuō)我怎么就攤上這事吹害∶荆” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,823評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵赠制,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我挟憔,道長(zhǎng)钟些,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,204評(píng)論 1 292
  • 正文 為了忘掉前任绊谭,我火速辦了婚禮政恍,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘达传。我一直安慰自己篙耗,他們只是感情好迫筑,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著宗弯,像睡著了一般脯燃。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蒙保,一...
    開(kāi)封第一講書(shū)人閱讀 51,190評(píng)論 1 299
  • 那天辕棚,我揣著相機(jī)與錄音,去河邊找鬼邓厕。 笑死逝嚎,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的详恼。 我是一名探鬼主播补君,決...
    沈念sama閱讀 40,078評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼昧互!你這毒婦竟也來(lái)了挽铁?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,923評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤硅堆,失蹤者是張志新(化名)和其女友劉穎屿储,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體渐逃,經(jīng)...
    沈念sama閱讀 45,334評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡够掠,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了茄菊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片疯潭。...
    茶點(diǎn)故事閱讀 39,727評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖面殖,靈堂內(nèi)的尸體忽然破棺而出竖哩,到底是詐尸還是另有隱情,我是刑警寧澤脊僚,帶...
    沈念sama閱讀 35,428評(píng)論 5 343
  • 正文 年R本政府宣布相叁,位于F島的核電站,受9級(jí)特大地震影響辽幌,放射性物質(zhì)發(fā)生泄漏增淹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評(píng)論 3 326
  • 文/蒙蒙 一乌企、第九天 我趴在偏房一處隱蔽的房頂上張望虑润。 院中可真熱鬧,春花似錦加酵、人聲如沸拳喻。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,672評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)冗澈。三九已至钦勘,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間渗柿,已是汗流浹背个盆。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,826評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留朵栖,地道東北人颊亮。 一個(gè)月前我還...
    沈念sama閱讀 47,734評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像陨溅,于是被迫代替她去往敵國(guó)和親终惑。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評(píng)論 2 354