【劍指offer】二叉樹以及二叉搜索樹的最近公共祖先

面試題68 - I. 二叉搜索樹的最近公共祖先

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

百度百科中最近公共祖先的定義爲:“對於有根樹 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, 因爲根據定義最近公共祖先節點可以爲節點本身。

先來說明二叉搜索樹的性質,其左子樹上的結點都小於根結點,右子樹上的結點都大於根節點。並且左右子樹都是二叉搜索樹

利用遞歸進行求解

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(p.val<root.val && q.val < root.val){
            return lowestCommonAncestor(root.left,p,q);//在左子樹找
        }
        if(p.val>root.val && q.val > root.val){
            return lowestCommonAncestor(root.right,p,q);//在右子樹找
        }
        return root;//如果左右子樹都沒有滿足的公共結點,則root就是公共結點。
    }
}

面試題68 - II. 二叉樹的最近公共祖先

難度簡單52

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

百度百科中最近公共祖先的定義爲:“對於有根樹 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 爲不同節點且均存在於給定的二叉樹中。

解題思路:通過路徑打印,然後在路徑中找到第一個相等的值就是最近的公共祖先了。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public static boolean getPath(TreeNode root,TreeNode node,Stack<TreeNode> stack){
        if(root == null)
            return false;
        stack.push(root);    
        if(root == node)
            return true;
        if(getPath(root.left,node,stack))
            return true;
        if(getPath(root.right,node,stack))
            return true;
        stack.pop();//當前結點既不是node結點,而且他的左右子樹也沒有這個結點,所以這個結點不在node的路徑上,所以就從棧中刪除當前結點。
        return false;                
    }
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        Stack<TreeNode> stack1 = new Stack<>();
        Stack<TreeNode> stack2 = new Stack<>();
        getPath(root,p,stack1);
        getPath(root,q,stack2);
        while(stack1.size() != stack2.size()){
            if(stack1.size()>stack2.size()){
                stack1.pop();
            }else{
                stack2.pop();
            }
        }
        while(stack1.size() != 0){
            if(stack2.peek() == stack1.peek()){
                break;
            }else{
                stack1.pop();
                stack2.pop();
            }
        }
        return stack1.peek();
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章