用人不宜刻,刻则思效者去。
交友不宜滥,滥则贡谀者来。
首先我们都能想到,如果能从上到下访问就好了。这样就可以很轻松的找到公共祖先啦。
二叉树如何实现自下而上的查找呢?
回溯啊,二叉树回溯的过程就是从低到上。
后序遍历就是天然的回溯过程,最先处理的一定是叶子节点。
这里借用代码随想录的图,便于理解整个回溯的过程。
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == null || root.val == p.val || root.val == q.val){
return root;
}
TreeNode left = lowestCommonAncestor(root.left,p,q);
TreeNode right = lowestCommonAncestor(root.right,p,q);
// 左右子树返回值均为null, p和q均不在树中,即没有LCA
if(left == null && right == null){
return null;
}
//左右子树的返回值都不为null,表明p和q分别在左右子树中。即root为LCA
if(left != null && right != null){
return root;
}
// p 和 q 其中之一,在一个在左or右子树中。即不为null的就是那个LCA
return (left != null) ? left : right;
}
}
二叉搜索树(BST) 属于二叉树,So 上面的解法 完全可以用来解决这道题。但是由于是BST,所以我们可以利用BST的性质来解决此题。
PS: 二叉搜索树(BST) 的性质:左子树的值比根节点小,右子树的值比根节点大( 左小右大)
递归解法
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == null || p.val == root.val || q.val == root.val){
return root;
}
// 如果p,q的值都大于root的值,说明p,q都位于右子树上
if(p.val > root.val && q.val > root.val){
return lowestCommonAncestor(root.right,p,q);
// 如果 p, q的值都小于root的值,说明p,q都位于左子树上。
}else if(p.val < root.val && q.val < root.val){
return lowestCommonAncestor(root.left,p,q);
}else{
return root;
}
}
}
非递归解法
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
while(root != null){
if(p.val > root.val && q.val > root.val){
root = root.right;
}else if(p.val < root.val && q.val < root.val){
root = root.left;
}else {
return root;
}
}
return root;
}
}