代码随想录算法训练营第二十天| 530. 二叉搜索树的最小绝对差,501. 二叉搜索树中的众数,236. 二叉树的最近公共祖先
530.二叉搜索树的最小绝对差
题目链接:二叉搜索树的最小绝对差
双指针
这道双指针的两根指针运动的轨迹是中序遍历(左中右),pre指针一直尾随cur指针。这里尾随,因为是左中右的原因,中和左右,以及中和右左,也只是会比较到的,由于是二叉搜索树,所以只比较相邻的两个node之间的差就够了(中-左,右-中)。
def traverse(root):
nonlocal result, pre
if not root:
return
traverse(root.left)
if pre:
result = min(result,root.val-pre.val) #顺序是左中右,pre跟着root所以不用abs
pre = root
traverse(root.right)
中序遍历,
最里层,root直接一路走到左下角的1,然后1的left是None,无事发生,此时pre也是None,不进if pre,之后让pre = 1这个node,1的right是None,继续无事发生。
往上一层,root是2,root.left走过了,此时pre是1,所以进if pre,得到result=2-1=1,然后pre变成2
root.right是3,也可以得到result=3-2=1,pre变成3
再上一层,root是4,但此时pre是3,所以这里还是可以得到4-3这个结果的!!
这也是昨天验证二叉搜索树里可以解决陷阱的原因。
视频解析:卡哥牛逼
class Solution:
def getMinimumDifference(self, root: Optional[TreeNode]) -> int:
pre = None
result = inf
def traverse(root):
nonlocal result, pre
if not root:
return
traverse(root.left)
if pre:
result = min(result,root.val-pre.val) #顺序是左中右,pre跟着root所以不用abs
pre = root
traverse(root.right)
traverse(root)
return result
普通递归
用前序(左中右)把所有node收集到一个list里,然后找相邻元素的最小值。
class Solution(object):
def getMinimumDifference(self, root):
"""
:type root: TreeNode
:rtype: int
"""
def traverse(root):
if not root:
return
traverse(root.left)
res.append(root.val)
traverse(root.right)
res = []
traverse(root)
result = float("inf")
for i in range(len(res)-1):
result = min(result,(res[i+1]-res[i]))
return result
迭代
class Solution(object):
def getMinimumDifference(self, root):
"""
:type root: TreeNode
:rtype: int
"""
queue = collections.deque()
queue.append(root)
cur = root
pre = None
result = float("inf")
while queue:
while cur.left:
cur = cur.left
queue.append(cur)
cur1 = queue.pop()
if pre:
result = min(result,cur1.val-pre.val)
pre = cur1
if cur1.right:
cur = cur1.right
queue.append(cur)
return result
501. 二叉搜索树中的众数
题目链接:二叉搜索树中的众数
普通二叉树的众数
class Solution:
def findMode(self, root: Optional[TreeNode]) -> List[int]:
d = defaultdict(int)
def traverse(root):
nonlocal d
if not root:
return
traverse(root.left)
d[root.val] += 1
traverse(root.right)
traverse(root)
l = max(d.values())
re = []
for i in d:
if d[i] == l:
re.append(i)
return re
搜索二叉树的众数
用双指针遍历整个树,如果pre和cur的值相等,那么计数,如果不等就重新开始新的计数,初始设定maxcount是1,如果数到count和maxcount一样大的那么就计入此刻的root,如果比maxcount大的就重置list再放此刻的root。
class Solution:
def findMode(self, root: Optional[TreeNode]) -> List[int]:
count = 1
maxcount = 1
pre = None
res = []
def traversal(root):
nonlocal count, maxcount, pre, res
if not root:
return
traversal(root.left)
if pre and (pre.val == root.val):
count += 1 #计数
elif pre and (pre.val != root.val):
count = 1 #count重置
pre = root
if count == maxcount:
res.append(root.val)
elif count > maxcount:
res = []
maxcount = count
res.append(root.val)
traversal(root.right)
traversal(root)
return res
236. 二叉树的最近公共祖先
题目链接:二叉树的最近公共祖先
这里的逻辑是往树的两边找p和q,找到的话就往上传,用后序遍历(左右中),所以就是self.lowestCommonAncestor(root.left,p,q)
和self.lowestCommonAncestor(root.right,p,q)
,root是被传进去的,所以自己没有改变,还是根节点,所以如果左右都找到了就可以输出根节点,一边找到了另一边没有就说明一边找到的那个就最近公共祖先,所以直接输出就行了。
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
if not root:
return root
if (root == p) or (root == q):
return root
left = self.lowestCommonAncestor(root.left,p,q)
right = self.lowestCommonAncestor(root.right,p,q)
if left and right:
return root
if (not left) and (right):
return right
if (not right) and left:
return left