力扣面试150题--二叉树的最近公共祖先

Day 53

题目描述

思路

初次思路:转化为中序和后序来找祖先,具体见代码。

java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<TreeNode>hou;
    public List<TreeNode>mid;
    public Map<TreeNode,Integer>midhao;
    public Map<TreeNode,Integer>houhao;
    int i=0;
    int j=0;
    public void houpai(TreeNode root){
        if(root==null){
            return;
        }
        houpai(root.left);
        houpai(root.right);
        hou.add(root);//保存到后序遍历数组中
        houhao.put(root,j);//记录序号
        j++;
    }
     public void midpai(TreeNode root){
        if(root==null){
            return;
        }
        midpai(root.left);
        mid.add(root);//保存在中序遍历数组
        midhao.put(root,i);//记录序号
        i++;
        midpai(root.right);
    }
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
       hou=new ArrayList<TreeNode>();
       mid=new ArrayList<TreeNode>();
       midhao=new HashMap<TreeNode,Integer>();
       houhao=new HashMap<TreeNode,Integer>();
       houpai(root);
       midpai(root);
       int houp,midp;
       int houq,midq;
       houp=houhao.get(p);
       midp=midhao.get(p);//找到p在后序和中序遍历的序号
       houq=houhao.get(q);
       midq=midhao.get(q);//找到q在后序和中序遍历的序号
       i=houhao.get(root);
       j=midhao.get(root);//找到根在后序和中序遍历的序号
       int midbeg,midend,houbeg,houend;
       midbeg=0;//某一子树中序遍历的起点
       midend=mid.size()-1;//某一子树中序遍历的终点
       houbeg=0;//某一子树后序遍历的起点
       houend=hou.size()-1;//某一子树后序遍历的终点
       while(true){
        if((midq<=j&&midp>=j)||(midq>=j&&midp<=j)){//在同一子树就可以输出了
            return mid.get(j);
        }
        else{
            if(midq<j&&midp<j){//都在左子树
              //更新到左子树,排除掉所有的右子树
               midbeg=midbeg;
               int x=midend-j;//右子树的节点数
               midend=j-1;
               houbeg=houbeg;
               houend=houend-x-1;
               root=hou.get(houend);
               j=midhao.get(root);//更新根节点的序号
            }
            else{//都在右子树
                //更新到右子树,排除到所有的左子树
                int x=j-midbeg;//左子树的节点个数
                midbeg=j+1;
                midend=midend;
                houbeg=houbeg+x;
                houend=houend-1;
                root=hou.get(houend);
                j=midhao.get(root);//更新根节点的序号
            }
       }
    }
}
}

题解思路:我们可以用哈希表存储所有节点的父节点,然后我们就可以利用节点的父节点信息从 p 结点开始不断往上跳,并记录已经访问过的节点,再从 q 节点开始不断往上跳,如果碰到已经访问过的节点,那么这个节点就是我们要找的最近公共祖先。

java 复制代码
class Solution {
    Map<Integer, TreeNode> parent = new HashMap<Integer, TreeNode>();
    Set<Integer> visited = new HashSet<Integer>();

    public void dfs(TreeNode root) {//存储到hash表中每个节点的父节点
        if (root.left != null) {
            parent.put(root.left.val, root);
            dfs(root.left);
        }
        if (root.right != null) {
            parent.put(root.right.val, root);
            dfs(root.right);
        }
    }

    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        dfs(root);
        while (p != null) {
            visited.add(p.val);//将p的父节点不断加入到set中
            p = parent.get(p.val);
        }
        while (q != null) {
            if (visited.contains(q.val)) {
            //从q开始向上找父节点,如果找到第一个v存在于p的父节点集合SET说明就找到了二叉树的最近公共祖先
                return q;
            }
            q = parent.get(q.val);//接着找父节点
        }
        return null;
    }
}
相关推荐
Java致死11 分钟前
面试-操作系统
面试·操作系统
gufs镜像19 分钟前
Swift学习总结——使用Playground
前端·ios·面试
?abc!2 小时前
(哈希)128. 最长连续序列
算法·leetcode·哈希算法
Yrrr13 小时前
Redis 持久化机制详解:RDB、AOF 原理与面试最佳实践(AOF篇)
数据库·redis·面试·职场和发展
岁忧4 小时前
(LeetCode 每日一题) 2016. 增量元素之间的最大差值 (数组)
java·c++·算法·leetcode·职场和发展·go
一入JAVA毁终身4 小时前
面试第三期
面试·职场和发展
晴殇i4 小时前
3 分钟掌握图片懒加载核心技术:面试攻略
前端·面试·trae
前端小巷子5 小时前
跨标签页通信(四):SharedWorker
前端·面试·浏览器
周壮5 小时前
03 面试官考察与 CAP 有关的分布式理论
分布式·面试