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)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。