力扣235
https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-search-tree/
二叉搜索树的性质:左子树<根<右子树。因此当前节点要做的事情很简单:
我们只需要判断当前节点和要找的两个节点p, q比较大小
root.val比p.val和q.val都小,公共节点肯定不是他,在右子树
root.val比p.val和q.val都大,公共节点肯定不是他,在左子树
root.val在p.val和q.val之间,公共节点肯定是他
对于特殊情况:公共祖先就是p或者q的情况,因为我们递归从上往下遍历,先到达的那个是p就返回p,是q就返回q,所以这个特殊情况的判断放在前序遍历的位置
1 2 3 4 5 6 7 8 9 10 11 12
| public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { if(root == null) return root;
if (p == root || q == root) return root;
if (p.val < root.val && q.val < root.val) { return lowestCommonAncestor(root.left, p, q); }else if (p.val > root.val && q.val > root.val) { return lowestCommonAncestor(root.right, p, q); } return root; }
|
妙就妙在判断的顺序,先判断全左和全右,这样就不需要判断p和q哪个大,夹在中间时p < root < q还是q < root < p
力扣236
https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/
思考过程:没有了二叉排序树的性质,那只能左右遍历了,当前节点要做的事:如果左右子树包含p,q就说明当前节点是最近公共祖先。那p,q肯定不会说一直都在同一层,所以是由下层返回的才能判断,后序遍历位置理所当然
思路:后序遍历位置,左右递归后返回的结果记录下来,返回的结果应该是:如果是要找的p或q,那么一直沿父节点返回,否则直接返回null。那么递归回来的时候,公共祖先左右两边节点就是p和q,否则的话左右两边为null
看图比较直观:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| 后序遍历,所以从叶子节点开始,假设树如下,要找的节点是8和4 3 / \ / \ / \ / \ 5 1 / \ / \ / \ / \ 6 2 0 8 / \ 7 4 3 / \ / \ / \ / \ 5 1 / \ / \ / \ / \ 6 2 0 8 / \ null 4 3 / \ / \ / \ / \ 5 1 / \ / \ / \ / \ null 4 null 8 / \ null 4 3 / \ / \ / \ / \ 4 8 / \ / \ / \ / \ null 4 null 8 / \ null 4 3 返回到当前节点为3时,左右都不为null(不需要判断具体左和右),成了 / \ / \ / \ / \ 4 8 / \ / \ / \ / \ null 4 null 8 / \ null 4
|
代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13
| public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { if(root == null) return root;
if (p == root || q == root) return root;
TreeNode left = lowestCommonAncestor(root.left,p,q); TreeNode right = lowestCommonAncestor(root.right,p,q);
if(left!=null && right != null) return root; else if (left != null) return left; else if (right != null) return right; return null; }
|
妙就妙在只需要判断是否为null即可而不需要判断是否是p还是q,不为null那么一定是p或者q,左右都不为null一定是公共祖先
特殊情况:p,q恰好是公共祖先的特判刚好也能判到