题目描述:
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]
来源:力扣(LeetCode)
思路:
1)和236题不同:
①普通二叉树:需要按照回溯的方式,从底层往上返回公共子节点!最先返回的就是最深,找到 之后往上返回该节点
②BST是有序,带有方向性的二叉树:也就是该题可以按照区间的方式进行!从上往下递归,前序比较的形式,也必须先序比较,此时第一次发现的就是公共子节点;再往下走还会出现存在于区间中的情况,但是此时已经不是公共祖先节点!
③要注意 左右都是闭区间!为了保证 两个节点在同一侧的子树上!
2)该题只有三种情况:
①当前节点值在目标区间左侧;去遍历查找右侧
②当前节点值在目标区间右侧;去遍历查找左侧;
③当前节点落在区间中,包括边界,就返回!
这一点需要理解,感觉是这道题思路的关键!
代码:
1)递归
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
return dfs(root,p,q);
}
//递归查找!和普通二叉树不同
//传入当前节点,和需要的 两个节点;
TreeNode dfs(TreeNode root,TreeNode p,TreeNode q){
//此时走到了底
if(root == null) return null;
//只走一边
if(root.val < p.val && root.val < q.val) return dfs(root.right,p,q);
else if(root.val > p.val && root.val > q.val) return dfs(root.left,p,q);
else return root;
}
}
2)迭代
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 return root;
}
return null;
}
}
3)普通二叉树
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
//1.到底没找到,就返回的是null
//2.找到一个就返回:要么另一个包含在这一点下面;要么下面也没有
if(root == null || root == p || root == q) return root;
//走到这儿,说明该节点,上面的都不符合
//分别拿到左右子树返回上来的内容,进行查看
//这一步就递归,走到了底
TreeNode left = lowestCommonAncestor(root.left,p,q);
TreeNode right = lowestCommonAncestor(root.right,p,q);
//开始判断
if(left == null && right == null) return null;//没找到
else if(left == null && right != null) return right;//返回上来一个,从下往上找的
else if(left != null && right == null) return left;
else return root;//此时左右子树都返回回来内容,则此节点就符合!
//之后每次往上抛的还是该节点
}
}