难度:☆2
本题核心:中序遍历二叉搜索树节点的数值,可以得到单调递增的有序序列。求最小绝对差,相当于求单调递增序列相邻项之差的最小值。
二叉搜索树本身是有序的,要利用好这一特点。
最直观的解法:中序遍历这棵树,得到一个数组,再用前后双指针,求数组相邻项之差的最小值。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def getMinimumDifference(self, root: Optional[TreeNode]) -> int:
array = []
self.inOrder(root, array)
left, right = 0, 1
minDiff = array[right] - array[left]
while right < len(array):
if array[right] - array[left] < minDiff:
minDiff = array[right] - array[left]
left += 1
right += 1
return minDiff
def inOrder(self, node: Optional[TreeNode], array: list) -> None:
if not node:
return None
self.inOrder(node.left, array) # 左
array.append(node.val) # 中
self.inOrder(node.right, array) # 右
用双指针,比较前一个节点和后一个节点的大小。注意返回值的初始化是 sys.maxsize
。不要忘记更新 pre
。
class Solution:
def __init__(self):
self.pre = None
self.minDiff = sys.maxsize
def getMinimumDifference(self, root: Optional[TreeNode]) -> int:
self.inOrder(root)
return self.minDiff
def inOrder(self, cur: Optional[TreeNode]) -> None:
if not cur:
return None
self.inOrder(cur.left) # 左
if self.pre: # 中
self.minDiff = min(self.minDiff, cur.val-self.pre.val)
self.pre = cur # 节点值是递增的,更新pre
self.inOrder(cur.right) # 右
用栈模拟递归过程,实现中序遍历。双指针计算前后节点的差值,与返回值作比较。类似 98 题。
class Solution:
def getMinimumDifference(self, root: Optional[TreeNode]) -> int:
stack = []
cur = root
pre = None # 记录前一个节点
result = float('inf')
while cur or stack:
if cur: # 一直访问到最底层
stack.append(cur)
cur = cur.left # 左
else: # 逐一处理节点
cur = stack.pop() # 中
if pre: # 计算当前节点和之前节点的差值
result = min(result, cur.val-pre.val)
pre = cur # 节点值是递增的,更新pre
cur = cur.right # 右
return result
难度:☆3
和 530 题类似,还是利用递归法和双指针实现中序遍历。注意:比较双指针、比较计数值的各种情况要分类讨论清楚。只需要遍历一次。
class Solution:
def __init__(self):
self.pre = None # 上一个节点的指针
self.count = 0 # 当前节点值的计数
self.maxCount = 0 # 最大节点值的计数
self.result = [] # 返回的结果数组
def findMode(self, root: Optional[TreeNode]) -> List[int]:
self.inOrder(root)
return self.result
def inOrder(self, cur: Optional[TreeNode]) -> None:
if not cur:
return None
self.inOrder(cur.left) # 左
if not self.pre: # 中
self.count = 1 # 第一个节点
elif self.pre.val == cur.val: # 与前一个节点数值相同
self.count += 1
elif self.pre.val != cur.val: # 三种比较的情况讨论清楚
self.count = 1
if self.count == self.maxCount:
self.result.append(cur.val)
elif self.count > self.maxCount:
self.maxCount = self.count
self.result = [cur.val] # 清空result并放入当前节点值
self.pre = cur # 更新pre指针
self.inOrder(cur.right) # 右
return
利用迭代法和双指针实现中序遍历。中间节点的逻辑类似解法 a,也只需遍历一次。
class Solution:
def findMode(self, root: Optional[TreeNode]) -> List[int]:
stack = []
cur = root
pre = None # 上一个节点的指针
maxCount, count = 0, 0 # 最大节点值/当前节点值的计数
result = [] # 返回的结果数组
while cur or stack:
if cur: # 一直访问到最底层
stack.append(cur)
cur = cur.left # 左
else: # 逐一处理节点
cur = stack.pop() # 中
if not pre: # 第一个节点
count = 1
elif pre.val == cur.val: # 与前一个节点数值相同
count += 1
elif pre.val != cur.val: # 三种比较的情况讨论清楚
count = 1
if count == maxCount:
result.append(cur.val)
elif count > maxCount:
maxCount = count
result = [cur.val] # 清空result并放入当前节点值
pre = cur # 更新pre指针
cur = cur.right # 右
return result
难度:☆4
二叉树只能从上往下遍历,如果想从下往上遍历,需要用后序遍历(即回溯)实现。在回溯的过程中,即使已经找到结果了,依然要把其他节点遍历完,因为要使用递归函数的返回值(left
和 right
)做逻辑判断,将结果返回给头节点。
在递归函数有返回值的情况下:如果要搜索一条边,递归函数返回值不为空的时候,立刻返回;如果搜索整个树,直接用一个变量 left
或 right
接住返回值,这个 left
或 right
后序还有逻辑处理的需要,也就是后序遍历中处理中间节点的逻辑(也是回溯)。[摘自:代码随想录]
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
if not root:
return None
if root == p or root == q:
return root
leftSubTree = self.lowestCommonAncestor(root.left, p, q) # 左
rightSubTree = self.lowestCommonAncestor(root.right, p, q) # 右
if leftSubTree and rightSubTree: # 中
return root
elif leftSubTree and not rightSubTree:
return leftSubTree
elif not leftSubTree and rightSubTree:
return rightSubTree
elif not leftSubTree and not rightSubTree: # 讨论四种情况
return None
精简版,真是思路复杂、代码简短:
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) # 右
if left and right: # 中
return root
if left:
return left
return right