LeetCode 236. 二叉树的最近公共祖先 (Java解法)

链接:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree
在这里插入图片描述
注意这里的问题其实就告诉了做题的人,这里既没有父亲节点,也没有二叉搜索树的性质。
LCA的问题,一般来说就是几种套路

1 塑造父亲节点

一般来说,现确定有没有父节点的这个附加功能,如果有父节点,那么就是两个链表,寻找公共点的问题。
如果没有父亲节点这个附加功能,那么就要构造出一个子节点和父亲节点相关联的映射表来。
这个是万能的解,走过一遍,然后用个HashMap来做个子节点和父亲节点映射关系的map.
至于你遍历的时候用的是前中后序遍历,还是层序遍历,这个都无关紧要了。

public static TreeNode lowestCommonAncestorByFatherMap(TreeNode root, TreeNode p, TreeNode q)  {
    if (root == null || p == root || q == root) {
        return root;
    }
    if (p == null) {
        return q;
    }
    if (q == null) {
        return p;
    }
    Map<TreeNode, TreeNode> fatherMap = new HashMap<>();
    Queue<TreeNode> queue = new LinkedList<>();
    queue.add(root);
    while (queue.size() > 0) {
        int count = queue.size();
        while (count > 0) {
            TreeNode temp = queue.poll();
            if (temp.left != null) {
                fatherMap.put(temp.left, temp);
                queue.offer(temp.left);
            }
            if (temp.right != null){
                fatherMap.put(temp.right, temp);
                queue.offer(temp.right);
            }
            count--;
        }
    }
    HashSet<TreeNode> paths = new HashSet<>();
    while (p != null) {
        paths.add(p);
        p = fatherMap.get(p);
    }
    TreeNode ans = null;
    while (q != null ){
        if (paths.contains(q)) {
            ans = q;
            break;
        }
        q = fatherMap.get(q);
    }
    return ans;
}

2 找路径法

这个方法其实不咋好,其实就是先遍历把所有的点给遍历了,然后按照中序遍历来存储点,放入list中。
然后寻找点的位置,然后把所有第一个点的位置给放到set中,然后在利用第二个做同样的操作。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
	List<TreeNode> list = new ArrayList<>();
	Set<TreeNode> pathP = new HashSet<TreeNode>();
	TreeNode result = null;
	public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
		allPath(root);
		searchP(p);
		searchQ(q);
		return result;
	}

	public void searchP(TreeNode p) {
		int indexP = list.indexOf(p);
		TreeNode preNode = p;
		pathP.add(p);
		for (int i = indexP; i >= 0; --i) {
			TreeNode tempNode = list.get(i);
			if (tempNode.left == preNode || tempNode.right == preNode) {
				pathP.add(tempNode);
				preNode = tempNode;
			}
		}
	}

	public void searchQ(TreeNode q) {
		int indexQ = list.indexOf(q);
		TreeNode preNode = q;
		for (int i = indexQ; i >= 0; --i) {
			TreeNode tempNode = list.get(i);
			if (tempNode == preNode || tempNode.left == preNode || tempNode.right == preNode) {
				if (pathP.contains(tempNode)) {
					result = tempNode;
					return;
				}
				preNode = tempNode;
			}
		}
		result = q;
	}

	public void allPath(TreeNode node) {
		if (node == null) {
			return;
		}
		list.add(node);
		allPath(node.left);
		allPath(node.right);
	}
}

3递归找节点

这个比较难以想到,首先就是你精通后序遍历了,先找左边的那个子节点他爹节点,然后找右边的节点的他爹的节点,然后两个比较一下子,看看是不是左右的两个节点都存在,都存在就返回root。
如分别左右节点都找到了,那么当前的根节点肯定就是结果了。

public TreeNode betterLowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
	if (root == null || p == root || q == root) {
		return root;
	}
	TreeNode left = betterLowestCommonAncestor(root.left, p, q);
	TreeNode right = betterLowestCommonAncestor(root.right, p, q);
	if (left != null && right != null) {
		return root;
	}
	if (left != null) {
		return left;
	}
	if (right != null) {
		return right;
	}
	return null;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值