在求解“最近公共祖先”的问题时,会遇到两种问题,一种是基于树状结构下求公共祖先、一种是一组带有连续编号的数字在树的结构下进行布局。
题目一:
将一棵无穷大满二叉树的结点按根结点一层一层地从左往右编号,根结点编号为1。现给定a,b为两个结点。设计一个算法,返回a、b最近的公共祖先的编号。注意其祖先也可能是结点本身。
题目二:
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/
看完本章题解可以点开两个题目的链接试试~~~
题目一解析:
若根节点为1,那么p和q的根节点判定可以分为两种情况。
1.若p == q,那么p和q的最近公共祖先则可以表示为p和q中任意一个值,表明此时已经找到该两个节点的最近公共祖先,此时函数调用结束。
2.若p > q或者q > q,那么需要每次挑出p和q中的最大值,进行取模2运算,直到回归到第一种情况,返回最近共祖祖先值,调用函数结束。
Java解决函数代码如下:
import java.util.*;
public class LCA {
public int getLCA(int a, int b) {
// write code here
while(a != b) {//每次取最大值进行模2运算,直至a和b两值相同
if(a > b) {
a /= 2;
} else {
b /= 2;
}
}
return a;
}
}
题目二解析:
在每个节点的判定节点时,可分为如下情况:
1.此时根节点为null或者左节点或者右节点为null时,返回null,表明两节点无最近公共祖先,结束此次函数调用。
2.此时左节点为null且右节点不为null时,返回右节点的值。
3.此时右节点为null且左节点不为null时,返回左节点的值。
4.此时左节点和右节点都不为null时,返回左右节点的根节点值。
每次递归查询树状结构的左子树和右子树,通过前面的4种条件判定当前最近公共祖先的值,并返回结果。
Java解决问题代码如下:
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == null) return null;
if(p == null || q == null) return null;
if(root == p || root == q) return root;
TreeNode leftNode = lowestCommonAncestor(root.left,p,q);
TreeNode rightNode = lowestCommonAncestor(root.right,p,q);
if(leftNode != null && rightNode == null) return leftNode;
if(leftNode == null && rightNode != null) return rightNode;
if(leftNode != null && rightNode != null) return root;
return null;
}
}