力扣面试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;
    }
}
相关推荐
Nil2083 小时前
leetcode 5最长回文子串
算法·leetcode·职场和发展
m0_674571973 小时前
力扣 hot 100 python
python·算法·leetcode
救救孩子把3 小时前
AI面试八股文-14_14-MCP-Skill-Function Calling
人工智能·安全·面试·职场和发展·推理·mcp·functioncall
圣保罗的大教堂4 小时前
leetcode 3727. 最大交替平方和 中等
leetcode
Xin7705 小时前
LeetCode 200. 岛屿数量(DFS 深度优先遍历法)
leetcode
帷幕落秋5 小时前
进程服务与文件描述符
linux·运维·面试
帷幕落秋5 小时前
信号、Ctrl 组合键与进程状态
linux·运维·面试
预知同行5 小时前
Agent 开发正在降温,但「可治理」的火才刚点起来
面试
乌暮11 小时前
从 `println` 到生产级日志:Spring Boot 日志体系完全指南
java·开发语言·jvm·spring boot·后端·学习·面试
王中阳Go11 小时前
第一单交付完,我等 3 个月没复购:不是交付差,是这 3 件事没做
人工智能·后端·面试