zoukankan      html  css  js  c++  java
  • leetcode 236. Lowest Common Ancestor of a Binary Tree

    Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.

    According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes v and w as the lowest node in T that has both v and w as descendants (where we allow a node to be a descendant of itself).”

            _______3______
           /              
        ___5__          ___1__
       /              /      
       6      _2       0       8
             /  
             7   4
    

    For example, the lowest common ancestor (LCA) of nodes 5 and 1 is 3. Another example is LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself according to the LCA definition.

    分析:

    给定一棵二叉树,找到两个节点的最近公共父节点(LCA)。

    最近公共祖先是两个节点的公共的祖先节点且具有最大深度。

    这道题可以用分治法完成,

    分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。

    求出子问题的解,就可得到原问题的解。即一种分目标完成程序算法,简单问题可用二分法完成。

    当我们求解某些问题时,由于这些问题要处理的数据相当多,或求解过程相当复杂,使得直接求解法在时间上相当长,或者根本无法直接求出。

    对于这类问题,我们往往先把它分解成几个子问题,找到求出这几个子问题的解法后,再找到合适的方法,把它们组合成求整个问题的解法。

    如果这些子问题还较大,难以解决,可以再把它们分成几个更小的子问题,以此类推,直至可以直接求出解为止。

    运用分治策略解决的问题一般来说具有以下特点:
     
    1、原问题可以分解为多个子问题
     
    这些子问题与原问题相比,只是问题的规模有所降低,其结构和求解方法与原问题相同或相似。
     
    2、原问题在分解过程中,递归地求解子问题
     
    由于递归都必须有一个终止条件,因此,当分解后的子问题规模足够小时,应能够直接求解。
     
    3、在求解并得到各个子问题的解后
     
    应能够采用某种方式、方法合并或构造出原问题的解。
     
    这道题可以使用深度优先搜索的思路,从叶子节点开始向上查找,在这个过程中标记子树中出现的目标节点。
    实际要看的是递归函数和实际处理部分的相对位置,
    实际处理在上,那就是从上向下,因为先处理再递归,
    实际处理在下,那就是从下向上,因为先递归再处理,处理是等到递归返回之后做的。
     
    如果某侧子树中有目标节点,标记为那个目标节点,如果没有,标记为null。
    如果左子树、右子树都有标记,说明p、q位于根节点的两侧,最小公共祖先就是root了。
     
    查看左子树中是否有目标节点,没有则为null,
    查看右子树中是否有目标节点,没有则为null,
    如果left、 right都不为空,说明左右子树都有目标节点,目标节点就是root。
    如果某一侧有目标节点,则标记为目标节点。

    //////// 

    如果一个节点左子树有两个目标节点中的一个,右子树没有,那这个节点肯定不是最小公共祖先。
    如果一个节点右子树有两个目标节点中的一个,左子树没有,那这个节点肯定也不是最小公共祖先。
    只有一个节点正好左子树有,右子树也有的时候,才是最小公共祖先。

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    public class Solution {
        public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
            // 在root为根的二叉树中找A,B的LCA:
            // 如果找到了就返回这个LCA
            // 如果只碰到A,就返回A
            // 如果只碰到B,就返回B
            // 如果都没有,就返回null
            if (root == null) {
                return null;
            }
            if (root == p || root == q) {
                return root;
            }
            // Divide
            TreeNode left = lowestCommonAncestor(root.left, p, q);
            TreeNode right = lowestCommonAncestor(root.right, p, q);
            
            // Conquer
            if(left != null && right != null) {
                return root;
            }
            if (left != null) {
                return left;
            }
            if (right != null) {
                return right;
            }
            return null;
        }
    }

    根空返空,

    根等p或根等q,返根

    左子树递归,

    右子树递归,

    左非空且右非空返根,

    左非空返左,

    右非空返右,

    返空。

  • 相关阅读:
    HDU 1251 统计难题(Trie)
    归并排序求逆序数
    HDU 4565 So Easy(矩阵解公式)
    HDU 3306 Another kind of Fibonacci(矩阵+ll超时必须用int&输入必须取模&M必须是int类型)
    IDEA设置一直显示行号
    IntelliJ Idea 常用快捷键列表
    Intellij IDEA快捷键(转)
    Springmvc返回JSON格式到页面中文乱码问题
    java中Date类型无法获取数据库时分秒问题解决方法
    使用阿里大于实现手机验证码
  • 原文地址:https://www.cnblogs.com/iwangzheng/p/5771363.html
Copyright © 2011-2022 走看看