【LeetCode & 剑指offer 刷题笔记】目录(持续更新中...)
68 树中两个节点的最低公共祖先
题目:
求树中两个结点的最低公共祖先
思路:
考虑一下几种情况:
1、该树为二叉搜索树
二叉搜索树是排序树,位于左子树点的结点都比父结点小,而位于右子树的结点都比父结点大,只需要从树的根结点开始和两个输入的结点进行比较。
如果当前结点的值比两个结点的值都大,那么最低的公共父结点一定在左子树,下一步就是遍历左子树;
如果当前结点的值比两个结点的值都小,那么最低的公共父结点一定在右子树;下一步就是遍历右子树;
如果当前结点的值介于两个结点的值之间,那么它就是两个结点的公共父结点
,
第一个找到的就是最低的公共父结点
。
235
.
Lowest Common Ancestor of a Binary Search Tree
Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST.
According to the
definition of LCA on Wikipedia
: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow
a node to be a descendant of itself
).”
Given binary search tree: root = [6,2,8,0,4,7,9,null,null,3,5]
Example 1:
Input:
root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
Output:
6
Explanation:
The LCA of nodes
2
and
8
is
6
.
Example 2:
Input:
root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
Output:
2
Explanation:
The LCA of nodes
2
and
4
is
2
, since a node can be a descendant of itself
according to the LCA definition.
Note:
-
All of the nodes' values will be unique.
-
p and q are different and both values will exist in the BST.
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
/*
问题:二叉搜索树的最低公共祖先
方法:递归法
如果根节点的值大于p和q之间的较大值,说明p和q都在左子树中,那么此时我们就进入根节点的左子节点继续递归,如果根节点小于p和q之间的较小值,说明p和q都在右子树中,那么此时我们就进入根节点的右子节点继续递归,如果都不是,则说明当前根节点就是最小共同父节点,直接返回即可
*/
class
Solution
{
public
:
TreeNode
*
lowestCommonAncestor
(
TreeNode
*
root
,
TreeNode
*
p
,
TreeNode
*
q
)
{
if
(!
root
)
//空结点时返回空
return
nullptr
;
//从根结点开始递归
if
(
root
->
val
>
max
(
p
->
val
,
q
->
val
))
//如果p,q在当前结点左子树,则对左子树遍历
return
lowestCommonAncestor
(
root
->
left
,
p
,
q
);
else
if
(
root
->
val
<
min
(
p
->
val
,
q
->
val
))
//如果p,q在当前结点右子树,则对右子树遍历
return
lowestCommonAncestor
(
root
->
right
,
p
,
q
);
else
//如果当前结点在p,q之间,则为最低公共父结点(因为从上往下在遍历,故遇到的第一个满足此条件的就是)
return
root
;
}
};
2、该树为二叉树,结点中有指向父结点的指针
有了父结点,就可以找到任意结点到根结点的路径;因此:
分别找到从两个结点开始到根结点的路径,即两个链表;
然后找到两个链表的第一个公共结点,就是最低的公共父结点;
3、该树为普通的树
从根结点开始,dfs,分别找到到达两个结点的路径;
然后
找到两条路径的最后一个公共结点
,就是最低的公共父结点;
Lowest Common Ancestor of a Binary Tree
Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.
According to the
definition of LCA on Wikipedia
: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow
a node to be a descendant of itself
).”
Given the following binary tree: root = [3,5,1,6,2,0,8,null,null,7,4]
Example 1:
Input:
root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
Output:
3
Explanation:
The LCA of of nodes
5
and
1
is
3.
Example 2:
Input:
root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
Output:
5
Explanation:
The LCA of nodes
5
and
4
is
5
, since a node can be a descendant of itself
according to the LCA definition.
Note:
-
All of the nodes' values will be unique.
-
p and q are different and both values will exist in the binary tree.
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
/*
问题:普通二叉树的最低公共祖先
方法:递归法
这道题是普通是二叉树,不是二叉搜索树,所以就不能利用其特有的性质,所以我们只能在二叉树中来搜索p和q,从左右子树中分别找p,q,如果对于某个结点,左右分别有p,q,则说明该结点为最低公共祖先
题目中没有明确说明p和q是否是树中的节点,如果不是,应该返回NULL,而下面的方法就不正确了
不好理解
*/
class
Solution
{
public
:
TreeNode
*
lowestCommonAncestor
(
TreeNode
*
root
,
TreeNode
*
p
,
TreeNode
*
q
)
{
if (root == nullptr || p == root || q == root)
//如果p==root或者q==root,说明找到了p和q
return
root
;
TreeNode
*
left
=
lowestCommonAncestor
(
root
->
left
,
p
,
q
);
//找左子树中是否存在p或q,存在时返回p或q或者p,q的祖先结点,不存在时返回nullptr
TreeNode
*
right
=
lowestCommonAncestor
(
root
->
right
,
p
,
q
);
//找右子树中是否存在p或q
if
(
left
&&
right
)
//left和right分别有p或q,则其父结点root为p,q的最低公共祖先
return
root
;
else
return
left
?
left
:
right
;
//left同时有p,q,则left为公共祖先,(若left为空,则right为公共祖先)
}
};
/*
改进:在找完左子树的共同父节点时如果结果存在,且不是p或q,
那么不用再找右子树了,直接返回这个结果即可,同理,对找完右子树的结果做同样处理,参见代码如下:
*/
class
Solution
{
public
:
TreeNode
*
lowestCommonAncestor
(
TreeNode
*
root
,
TreeNode
*
p
,
TreeNode
*
q
)
{
if
(!
root
||
p
==
root
||
q
==
root
)
return
root
;
TreeNode
*
left
=
lowestCommonAncestor
(
root
->
left
,
p
,
q
);
if
(
left
&&
left
!=
p
&&
left
!=
q
)
return
left
;
//如果left不为空且不是p或q,则其为公共祖先
TreeNode
*
right
=
lowestCommonAncestor
(
root
->
right
,
p
,
q
);
if
(
right
&&
right
!=
p
&&
right
!=
q
)
return
right
;
if
(
left
&&
right
)
//left和right分别有p或q,则其父结点root为p,q的最低公共祖先
return
root
;
else
return
left
?
left
:
right
;
}
};