二叉搜索树的公共祖先
思路:搜索树一定是左<root<右,二分查找,root大于pq则pq公共祖先一定位于root左子树上,反之位于右子树,若pq在root两侧则root为公共祖先
时间复杂度O(N)空间复杂度O(1)
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
while root.val<min(p.val,q.val) or root.val>max(p.val,q.val):
if root.val>p.val and root.val>q.val:
root=root.left
if root.val<p.val and root.val<q.val:
root=root.right
return root
二叉树的最近公共祖先
思路1:层序遍历,构建一个hash表来存储子节点指向父节点
根据hash表找p或q回溯至root,新建一个list来存储回溯路径,然后对q回溯,并判断回溯的每一个节点是否在list内,第一个出现在list的为最近的公共祖先
class Solution:
def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode:
if p==root or q==root:return root
#hash表存节点指向
hash={}
que=collections.deque()
que.append(root)
while que:
for _ in range(len(que)):
i=que.popleft()
if i.left:
hash[i.left]=i
que.append(i.left)
if i.right:
hash[i.right]=i
que.append(i.right)
#tem存q的回溯节点
tem=[]
while q!=root:
tem.append(q)
q=hash[q]
#判断p的回溯路径是否在tem中
while p!=root:
if p in tem:return p
p=hash[p]
#不在,则root为公共祖先
return root
思路2:递归
采用前序遍历,递归中止条件:
1.越过叶子节点
2.遍历至q或p节点
返回root
递归函数作用:找pq公共祖先→找root.left和root.right两颗子树的公共祖先
1.若pq不在root的左右子树中,root不是公共祖先,return
2.pq分别在左右子树中,则root必定是公共祖先,return root
3.pq都在root的左子树,返回left,继续递归,都在右子树同理
class Solution:
def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode:
if not root or root == p or root == q: return root
left = self.lowestCommonAncestor(root.left, p, q)
right = self.lowestCommonAncestor(root.right, p, q)
#pq不在root左右子树中,root不是公共祖先
if not left and not right: return # 1.
if not left: return right # 3.
if not right: return left # 4.
#pq
return root # 2. if left and right: