【算法】【面试级】Hot100 236. 二叉树的最近公共祖先

1. 递归

分析

遇到二叉树,递归是一个常见的思路。

构造一个辅助函数,返回boolean,代表这个节点root是否是p或q的祖先。

如果左子树返回true 且右子树也返回true,root就是p和q的祖先
左右子树只要一个返回true,并且root是p或者q,root也是p和q的祖先。
为什么不用区分到底是哪种情况呢,因为根本区分不了,辅助函数的对错就没有区分

左是对的,假设它是p的祖先,则root不可能是p,root那一项如果是true,只能是root是q
左是对的,假设它是p和q的公共祖先,那么它应该已经被填入答案了,右就不可能有p或q,root也不可能是p或q,root就不是答案了

算法

//主函数
//1. 调用dfs函数

//dfs函数
//1. 检查边界条件
//2. 递归
//3. 检查root是否是p和q的公共祖先,如果是存入ans
//4. 返回root是否是p或q的祖先

代码

public class Solution {
	private TreeNode ans;
	
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
		ans = root;
		//调用dfs
		dfs(root, p, q);
		return ans;
    }

	private boolean dfs(TreeNode root, TreeNode p, TreeNode q){
		//1. 边界条件处理
		if(root == null){
			return true;
		}
		
		//2. 递归 左与右
		boolean lSon = dfs(root.left, p, q);
		boolean rSon = dfs(root.right, p, q);
		
		//3. 如果root是p和q的最近公共祖先 存入答案,再远的公共祖先不会被判定为true
		if((lSon && rSon) || ((lSon || rSon) && (root.val == p.val || root.val == q.val)){
			ans = root;
		}
		
		//4. 返回root是否是p或q的祖先
		return lSon || rSon || root.val == p.val || root.val == q.val;
	}
}

2. 遍历

分析

主函数
遍历p的祖先节点
标记为true
遍历q的祖先节点
遇到的第一个true就是答案

难点1 给定一个节点 找到父节点
采用HashMap,以节点的值为key,父节点为value
难点2 判断一个节点是否被访问过
采用HashSet

算法

//主函数
//1. 遍历p的祖先节点,都标记在HashSet visited里
//2. 遍历q的祖先节点,遇到第一个visited里有的结点则返回

//dfs 构建HashMap parent
//1. 递归
//2. 如果左子结点不为空,加入parent
//3. 如果右子结点不为空,加入parent

代码

public class Solution {
	private Map<Integer, TreeNode> parent = new HashMap<>();
	private Set<TreeNode> visited = new HashSet<>();
	
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
		dfs(root);
		//1. 遍历p的祖先节点,加入visited
		while(p != null){
			visited.add(p);
			p = parent.get(p.val);
		}
		//2. 遍历q的祖先节点,如果某节点在visited中,直接返回
		while(q != null){
			if(visited.contains(q)){
				return q;
			}
			q = parent.get(q.val);
		}
		return null;
    }

	private void dfs(TreeNode root){
		//1. 左
		if(root.left != null){
			dfs(root.left);
			parent.put(root.left.val, root);
		}
		//2. 右
		if(root.right != null){
			dfs(root.right);
			parent.put(root.right.val, root);
		}
		
	}
}
posted @ 2025-11-23 11:46  pangeding  阅读(9)  评论(0)    收藏  举报