1、二叉搜索树是一个有序树:每个二叉树都满足左子树上所有节点的值均小于它的根节点的值,右子树上所有节点的值均大于它的根节点的值;因此,它的中序遍历是一个升序序列,有没有重复元素根据具体题意而定
2、本次总结的题型,采用迭代循环的中序遍历+标记节点的思路解决,简单直观
二叉搜索树的性质,中序遍历完是一个递增序列!利用中序遍历的迭代循环形式,添加一个pre指针标记递增序列的上一个元素
'''
98. 验证二叉搜索树
给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。
有效 二叉搜索树定义如下:
节点的左子树只包含 小于 当前节点的数。
节点的右子树只包含 大于 当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。
示例 2:
输入:root = [5,1,4,null,null,3,6]
输出:false
解释:根节点的值是 5 ,但是右子节点的值是 4 。
思路:二叉搜索树的性质,中序遍历完是一个递增序列!利用中序遍历的迭代循环形式,添加一个pre指针标记递增序列的上一个元素
'''
class Solution:
# 用中序遍历的迭代循环形式,添加一个pre指针标记递增序列的上一个元素
def isValidBST(self, root: Optional[TreeNode]) -> bool:
if not root:
return True
stack = []
pre = None
cur = root
while cur != None or len(stack) > 0:
# 先访问到最底层最左侧的节点
if cur != None:
stack.append(cur)
cur = cur.left # 左
# 到达最左结点后处理栈顶结点
else:
cur = stack.pop() # 中:这个节点一定不为空
if pre != None and pre.val >= cur.val:
return False
pre = cur
cur = cur.right # 右
return True
思路:二叉搜索树的性质,中序遍历完是一个递增序列!那么序列中两两元素之间的差值肯定是最小的。利用中序遍历的迭代循环形式,添加一个pre指针标记递增序列的上一个元素,不断更新最小绝对差
'''
530. 二叉搜索树的最小绝对差
给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 。
差值是一个正数,其数值等于两值之差的绝对值。
示例 1:
输入:root = [1,0,48,null,null,12,49]
输出:1
思路:二叉搜索树的性质,中序遍历完是一个递增序列!那么序列中两两元素之间的差值肯定是最小的。
利用中序遍历的迭代循环形式,添加一个pre指针标记递增序列的上一个元素,不断更新最小绝对差
'''
class Solution:
def getMinimumDifference(self, root: Optional[TreeNode]) -> int:
stack = []
pre = None
cur = root
result = float('inf')
while cur != None or len(stack) > 0:
# 先访问到最底层最左侧的节点
if cur != None:
stack.append(cur)
cur = cur.left # 左
# 到达最左结点后处理栈顶结点
else:
cur = stack.pop() # 中:这个节点一定不为空
if pre != None:
result = min(result, cur.val - pre.val)
pre = cur
cur = cur.right # 右
return result
思路:二叉搜索树的性质,中序遍历完是一个递增序列!相当于对递增数组求众数。利用中序遍历的迭代循环形式,添加一个pre指针标记递增序列的上一个元素,同时为了一次遍历找到所有众数,需要额外再添加两个频率标志
'''
501. 二叉搜索树中的众数
给你一个含重复值的二叉搜索树(BST)的根节点 root ,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。
如果树中有不止一个众数,可以按 任意顺序 返回。
假定 BST 满足如下定义:
结点左子树中所含节点的值 小于等于 当前节点的值
结点右子树中所含节点的值 大于等于 当前节点的值
左子树和右子树都是二叉搜索树
示例 1:
输入:root = [1,null,2,2]
输出:[2]
思路:二叉搜索树的性质,中序遍历完是一个递增序列!相当于对递增数组求众数。
利用中序遍历的迭代循环形式,添加一个pre指针标记递增序列的上一个元素,同时为了一次遍历找到所有众数,需要额外再添加两个频率标志
'''
class Solution:
def findMode(self, root: Optional[TreeNode]) -> List[int]:
if not root:
return []
# 中序遍历BST得到递增序列
stack = []
cur = root
result = []
# 定义三个标志
pre = None # 第一次有效的标志
count, maxCount = 0, 0 # 统计频率,最大频率
while cur != None or len(stack) > 0:
# 一直遍历到最底层最左侧的节点
if cur != None:
stack.append(cur)
cur = cur.left # 左
else:
cur = stack.pop() # 根
# 1、统计单个数值的频率
if pre == None:
count = 1
elif cur.val != pre.val:
count = 1
elif cur.val == pre.val:
count += 1
# 2、维护result数组
if count == maxCount:
result.append(cur.val)
elif count > maxCount:
maxCount = count
result.clear() # python原来有清除函数
result.append(cur.val)
pre = cur
cur = cur.right # 右
return result
二叉搜索树的性质,中序遍历完是一个递增序列!很明显是用中序遍历逆序+标记的思路解决
本题与“1038. 从二叉搜索树到更大和树”相同
'''
538. 把二叉搜索树转换为累加树
1038. 从二叉搜索树到更大和树
给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。
提醒一下,二叉搜索树满足下列约束条件:
节点的左子树仅包含键 小于 节点键的节点。
节点的右子树仅包含键 大于 节点键的节点。
左右子树也必须是二叉搜索树。
示例 1:
输入:[4,1,6,0,2,5,7,null,null,null,3,null,null,null,8]
输出:[30,36,21,36,35,26,15,null,null,null,33,null,null,null,8]
思路:二叉搜索树的性质,中序遍历完是一个递增序列!很明显是用中序遍历逆序+标记的思路解决。
'''
class Solution:
def convertBST(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
# 很明显是用中序遍历逆序+标记的思路
stk = []
cur = root
s = 0
while cur != None or len(stk) > 0:
if cur != None:
stk.append(cur)
cur = cur.right # 右
else:
cur = stk.pop() # 中
s += cur.val
cur.val = s
cur = cur.left # 左
return root