首先看一道二叉搜索树的题
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]
示例 1:
输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
输出: 6
解释: 节点 2 和节点 8 的最近公共祖先是 6。示例 2:
输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
输出: 2
解释: 节点 2 和节点 4 的最近公共祖先是 2, 因为根据定义最近公共祖先节点可以为节点本身。来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/er-cha-sou-suo-shu-de-zui-jin-gong-gong-zu-xian-lcof
这道题可以利用BST的性质进行求解
因为平衡二叉树中任一根节点的值都小于其右节点的值,并大于其左节点的值。所以可以通过根节点的值与两个目标节点的值的大小关系来判断迭代的方向。
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
while (root != null) {
//如果当前节点的值比目标的两个节点值都小,向右迭代
if (root.val < p.val && root.val < q.val) root = root.right;
//同上
else if (root.val > p.val && root.val > q.val) root = root.left;
//当当前节点的值正好在目标两个节点的值中间的时候,当前节点即为答案
else break;
}
return root;
}
}
这种方法对普通的二叉树就不管用了,对于普通的二叉树我们需要对它进行依次遍历来判断某个根节点的左右子树中是否含有这两个目标节点,我们使用DFS的方法来解决。下图方法是返回的是
该根节点的左右子树包含目标节点的个数并以此来判定该节点是否为答案,也可以通过返回值为
boolean的方式来解题。
class Solution {
TreeNode ans = null;
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
int a = p.val;
int b = q.val;
judgeSum(root,a,b);
return ans;
}
//返回值为该根节点的左右子树包含目标节点的个数
public int judgeSum(TreeNode root,int a ,int b){
if(root == null) return 0;
int l = judgeSum(root.left,a,b);
int r = judgeSum(root.right,a,b);
//因为我们要返回第一个包含两个目标节点的根节点,所以要采用后续遍历的方法
//该段代码判断了包含两个目标节点的两种情况,即左右子树各包含一个或者根节点即为目标节点且左子树或右子树中包含目标节点
//判断ans是否为null是为了因为答案节点的上层节点也符合条件,所以通过这种方式进行标记
if(ans == null && ((l == 1 && r == 1) || ((root.val == a || root.val == b) && (l == 1 || r == 1)))) ans = root;
if(root.val == a || root.val == b) return 1 + l + r;
return l + r;
}
}