530. 二叉搜索树的最小绝对差
题目:给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 。
差值是一个正数,其数值等于两值之差的绝对值。
示例 1:
输入: root = [4,2,6,1,3]
输出: 1
解题思路
递归,中序遍历一遍二叉搜索树,当成有序数组,两两比较差值。
1 采用递归的方式进行中序遍历二叉搜索树。
2 在中序遍历的过程中,记录前一个节点的值,并计算当前节点值与前一个节点值的差值,更新最小差值。
3 由于二叉搜索树的中序遍历结果是一个有序序列,因此相邻节点的差值就是最小绝对差。
- 时间复杂度:O(n) 每个节点都会被访问到,复杂度是O(n)。
- 空间复杂度:O(n) 递归函数空间复杂度取决于递归栈的深度,最坏情况下二叉树为一条链时达到O(n)。
class Solution:
def getMinimumDifference(self, root: Optional[TreeNode]) -> int:
self.result = float("inf") # 最小差值
self.prev = None # 前一个节点
self.traverse(root)
return self.result
def traverse(self, root: Optional[TreeNode])->None:
if not root:
return
self.traverse(root.left)
# 中序位置,先更新差值,然后更新prev
if self.prev:
self.result = min(self.result, root.val - self.prev.val)
self.prev = root
self.traverse(root.right)
总结
注意本题必定有2个节点,否则需要讨论result没有答案的情况。
501. 二叉搜索树中的众数
题目:给你一个含重复值的二叉搜索树(BST)的根节点 root ,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。
如果树中有不止一个众数,可以按 任意顺序 返回。
假定 BST 满足如下定义:
- 结点左子树中所含节点的值 小于等于 当前节点的值
- 结点右子树中所含节点的值 大于等于 当前节点的值
- 左子树和右子树都是二叉搜索树
示例 1:
输入: root = [1,null,2,2]
输出: [2]
示例 2:
输入: root = [0]
输出: [0]
提示:
- 树中节点的数目在范围
[1, 104]内 -105 <= Node.val <= 105
解题思路
由于是二叉搜索树,中序遍历元素是有序递增的,相同元素只会连续出现,所以只需要用记录当前元素的频率curFreq,最大的频率maxFreq;然后如果curFreq=maxFreq时候,将当前的root.val加入结果列表;如果curFreq>maxFreq时候,需要重置结果为[root.val]。
- 时间复杂度:O(n)
- 空间复杂度:O(n)
class Solution:
def findMode(self, root: Optional[TreeNode]) -> List[int]:
self.maxFreq = -1 # 最长序列长度
self.curFreq = -1 # 当前元素的频率
self.mode = []
self.prev = None
self.traverse(root)
return self.mode
def traverse(self,root: Optional[TreeNode]) -> List[int]:
if not root:
return
self.traverse(root.left)
# 更新频率:prev空时候更新max、cur、mode;非none时,判断当前元素和之前的是否相等。
# prev空时初始化
if self.prev is None:
self.curFreq = 1
self.maxFreq = 1
self.mode = [root.val]
# prev非空时,看看当前元素和之前的是否能接续
else:
if root.val == self.prev.val:
self.curFreq += 1
if self.curFreq == self.maxFreq:
self.mode.append(root.val)
elif self.curFreq > self.maxFreq:
self.maxFreq = self.curFreq
self.mode = [root.val]
else:
# 不相等,重置cur
self.curFreq = 1
if self.curFreq == self.maxFreq: # 相等的时候追加,>时候重置
self.mode.append(root.val) # 追加
# 更新指针
self.prev = root
self.traverse(root.right)
总结
注意可能存在多个频率相同的众数。curFreq == maxFreq时候追加,curFreq > maxFreq时候重置mode。
236. 二叉树的最近公共祖先
题目:给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
示例 1:
输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出: 3
解释: 节点 5 和节点 1 的最近公共祖先是节点 3 。
示例 2:
输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
输出: 5
解释: 节点 5 和节点 4 的最近公共祖先是节点 5 。因为根据定义最近公共祖先节点可以为节点本身。
示例 3:
输入: root = [1,2], p = 1, q = 2
输出: 1
提示:
- 树中节点数目在范围
[2, 105]内。 -109 <= Node.val <= 109- 所有
Node.val互不相同。 p != qp和q均存在于给定的二叉树中。
解题思路
递归遍历左右子树,对于根节点root和p、q,有三种情况:
1 p在左边,q在右边,root是最近公共祖先
2 root不是p、q任何一个的公共祖先,返回None
3 p、q在root的同一侧,如果右子树无答案,返回左子树的公共祖先;如果左子树无答案,返回右边的。
- 时间复杂度:O(n)
- 空间复杂度:O(n)
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
# base case:
if not root:
return None
if root == p or root == q:
return root
left = self.lowestCommonAncestor(root.left, p, q)
right = self.lowestCommonAncestor(root.right, p, q)
# case1: left和right都有值,那就是root
if left is not None and right is not None:
return root
# case2:都没有公共祖先,none
if left is None and right is None:
return None
# case3:在一侧
return left if right is None else right
总结
注意base case如果root为p或q其中一个时候,最近的公共祖先只能是root。