235.二叉搜索树的最近公共祖先
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 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
, 因为根据定义最近公共祖先节点可以为节点本身。
说明:
- 所有节点的值都是唯一的。
- p、q 为不同节点且均存在于给定的二叉搜索树中。
思路
这道题我觉得给中等难度稍微高了点,只要利用二叉搜索树的特性,使用递归即可找到祖先。
1、若p小于root节点,q大于root节点(假设p<q)或者p或q等于root,则最近公共祖先即为root
2、若p,q都小于root,则在root左子树继续找
3、若都大于root,则在root右子树继续找。
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if ((p.val < root.val && q.val > root.val) || (p.val > root.val && q.val < root.val) || p.val == root.val || q.val == root.val) {
return root;
}
if (p.val < root.val && q.val < root.val) {
return lowestCommonAncestor(root.left, p, q);
} else {
return lowestCommonAncestor(root.right, p, q);
}
}
236.二叉树的最近公共祖先
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
示例 1:
输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1 输出:3 解释:节点5
和节点1
的最近公共祖先是节点3 。
示例 2:
输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4 输出:5 解释:节点5
和节点4
的最近公共祖先是节点5 。
因为根据定义最近公共祖先节点可以为节点本身。
示例 3:
输入:root = [1,2], p = 1, q = 2 输出:1
提示:
- 树中节点数目在范围
[2, 105]
内。 -109 <= Node.val <= 109
- 所有
Node.val
互不相同
。 p != q
p
和q
均存在于给定的二叉树中。
思路
主要难点在于递归的思路
终止条件:
1、当越过叶节点(root=null)返回null
2、当root=p或q,返回root
两种情况合并为返回root
递推工作:
开启递归左子节点,返回值即为left
开启递归右子节点,返回值即为right
返回值:
1、当left和right都为空,说明左右子树都不包含p,q,返回null
2、当left和right同时不为空,说明root是最近公共祖先,pq在root异侧,返回root
3、当left为空,right不为空,说明pq在root的右子树中,返回right
4.当right为空,left不为空,与3同理,返回left
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
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){
return right;
}
if(right==null){
return left;
}
return root;
}
}
总结
写递归的时候思路要清晰,从终止条件,递归流程,返回值三个角度去解决问题。