1. 程式人生 > 其它 >總結所有有關二叉樹公共祖先問題

總結所有有關二叉樹公共祖先問題

二叉樹公共祖先

滿二叉樹最近公共祖先

將一棵無窮大滿二叉樹的結點按根結點一層一層地從左往右編號,根結點編號為1。現給定a,b為兩個結點。設計一個演算法,返回a、b最近的公共祖先的編號。注意其祖先也可能是結點本身。
測試樣例:
2,3
返回:1

連結:https://www.nowcoder.com/questionTerminal/70e00e490b454006976c1fdf47f155d9
來源:牛客網

思路

因為是按照0,1,2,3這樣的滿二叉樹,所以可以直接用公式找到其父親節點

父親節點 = 孩子節點 / 2

找到最低層的那個節點,然後向上找兩個節點的父節點,判斷兩者父親節點是否相同

程式碼

import java.util.*;
public class LCA {
    public int getLCA(int a, int b) {
        if(a > b) {
            int tmp = a;
            a = b;
            b = tmp;
        }
        if(a == b) return a;
//b最大了
        while(a != b) {
            b =
b/2; if(b < a) { a = a/2; if(a == b) break; } } return a; } }

二叉搜尋樹的最近公共祖先

給定一個二叉搜尋樹, 找到該樹中兩個指定節點的最近公共祖先。

百度百科中最近公共祖先的定義為:“對於有根樹 T 的兩個結點 p、q,最近公共祖先表示為一個結點 x,滿足 x 是 p、q 的祖先且 x
的深度儘可能大(一個節點也可以是它自己的祖先)。”

例如,給定如下二叉搜尋樹: root = [6,2,8,0,4,7,9,null,null,3,5]

示例 1:

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

輸入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4 輸出: 2 解釋: 節點 2
和節點 4 的最近公共祖先是 2, 因為根據定義最近公共祖先節點可以為節點本身。

說明:

所有節點的值都是唯一的。 p、q 為不同節點且均存在於給定的二叉搜尋樹中。

在這裡插入圖片描述

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/er-cha-sou-suo-shu-de-zui-jin-gong-gong-zu-xian-lcof

思路

若 root.val < p.val,則 p 在 root 右子樹 中;
若 root.val > p.val,則 p 在 root 左子樹 中;
若 root.val = p.val ,則 p 和 root 指向 同一節點 。

程式碼-遍歷

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        while(true) {
            if(root.val > p.val && root.val > q.val) {
                root = root.left;
            }else if(root.val < p.val && root.val < q.val) {
                root = root.right;
            }else break;
        }
        return root;
    }
}

程式碼-遞迴

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root.val < p.val && root.val < q.val)
            return lowestCommonAncestor(root.right, p, q);
        if(root.val > p.val && root.val > q.val)
            return lowestCommonAncestor(root.left, p, q);
        return root;
    }
}

二叉樹的最近公共祖先

給定一個二叉樹, 找到該樹中兩個指定節點的最近公共祖先。

百度百科中最近公共祖先的定義為:“對於有根樹 T 的兩個結點 p、q,最近公共祖先表示為一個結點 x,滿足 x 是 p、q 的祖先且 x
的深度儘可能大(一個節點也可以是它自己的祖先)。”

例如,給定如下二叉樹: 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 解釋: 節點 5
和節點 1 的最近公共祖先是節點 3。 示例 2:

輸入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4 輸出: 5 解釋: 節點 5
和節點 4 的最近公共祖先是節點 5。因為根據定義最近公共祖先節點可以為節點本身。

說明:

所有節點的值都是唯一的。 p、q 為不同節點且均存在於給定的二叉樹中。

在這裡插入圖片描述

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/er-cha-shu-de-zui-jin-gong-gong-zu-xian-lcof

思路

  1. 根節點本身是否是p或者q當中的某個節點
  2. 遞迴根的左和根的右
    2.1 左右兩邊都不為空:root是公共祖先
    2.2 左邊不為空,右邊為空:左邊第一次找到的節點就是公共祖先
    2.3 左邊為空,右邊不為空:右邊第一個節點就是公共祖先
  3. 如果都沒有,則返回null

程式碼-遞迴

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root == null) return null;
        if(root == q || root == p) return root;

        TreeNode left = lowestCommonAncestor(root.left,p,q);
        TreeNode right = lowestCommonAncestor(root.right,p,q);

        if(left != null && right != null) return root;

        if(left != null) return left;

        if(right != null) return right;

        return null;
    }
}