# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def lowestCommonAncestor(self, root, p, q):
"""
:type root: TreeNode
:type p: TreeNode
:type q: TreeNode
:rtype: TreeNode
"""
def f(node,aim):
stack=[]
while node or stack:
if node:
if node==aim:
return True
stack.append(node)
node=node.left
else:
n=stack.pop()
node=n.right
else:
return False
if not root or root==p or root==q:
return root
stack=[]
re=root
while stack or re:
if re:
stack.append(re)
if re==p or re==q:
break
re=re.left
else:
node=stack.pop()
re=node.right
new=q if re==p else p
while stack:
a=stack.pop()
if f(a,new):
return a
搞了一下午终于算搞出来了,看题解发现看不懂,比葫芦画瓢也总是出现各种各样的问题,不如自己想个办法
通过中序遍历法,当发现p或q(假设为p)时break,然后全力找q。
其中有个秘诀就是break时其中的stack中的元素均为p的祖先且若存在pq的共同祖先必存在于stack中,我编写了一个新函数来判断q是否是某节点的子孙,对stack中从后向前依次判断即可
本思路的难点在于:为什么break时共同祖先一定在stack中,stack中并不包含p所有祖先,譬如若p不是一直处于二叉树的最左边,那么定会在是stack.pop()后右面,那么pop后就会丢掉p的一个祖先,但要理解这个祖先一定不是他们的共同祖先,因为这个祖先的左面是不存在p或q的,所以就算他是共同祖先也绝对不是深度最深的,所以可以排除
多调试了几次,执行用时基本控制在40-60ms,内存稳定在19.7或19.8MB,击败用户执行用时稳定98%以上,击败用户内存消耗稳定在97%-98%
其实本思路还可以继续优化,因为stack中除了p的左右面没有测过,其余的元素的左面都已经测试过了,所以把p单独拿出来测,其余的元素可以只测试右面,代码如下:
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def lowestCommonAncestor(self, root, p, q):
"""
:type root: TreeNode
:type p: TreeNode
:type q: TreeNode
:rtype: TreeNode
"""
def f(node,aim):
stack=[]
while node or stack:
if node:
if node==aim:
return True
stack.append(node)
node=node.left
else:
n=stack.pop()
node=n.right
else:
return False
if not root or root==p or root==q:
return root
stack=[]
re=root
while stack or re:
if re:
if re==p or re==q:
break
stack.append(re)
re=re.left
else:
node=stack.pop()
re=node.right
new=q if re==p else p
if f(re,new):
return re
while stack:
a=stack.pop()
if f(a.right,new):
return a
思路其实只是小小优化,相信对速度的影响不会太大,但绝对简化了代码,减小了服务器的工作量,但如果多次使用程序的话还是会出现效果的。