二叉搜索树(BST)
BST的特性:
1、对于 BST 的每⼀个节点 node,左⼦树节点的值都⽐ node 的值要⼩,右⼦树节点的值都⽐ node 的值⼤。
2、对于 BST 的每⼀个节点 node,它的左侧⼦树和右侧⼦树都是 BST。
同时,BST具备另一个重要性质:BST 的中序遍历结果是有序的(升序)。
下面本文将从实例角度来理解BST的特性以及该重要性质。
230. 二叉搜索树中第K小的元素
解法:中序遍历
已知BST的中序遍历结果是有序的(升序),因此我们可以通过中序遍历找到第k小的元素。
class Solution:
def kthSmallest(self, root: Optional[TreeNode], k: int) -> int:
result = 0
rank = 0
def traverse(node):
nonlocal result
nonlocal rank
if not node:
return
traverse(node.left)
rank += 1
if rank == k:
result = node.val
traverse(node.right)
traverse(root)
return result
538. 把二叉搜索树转换为累加树
解法:反向中序遍历
针对二叉树问题,明确每个节点「该做什么」以及「什么时候做」。对于该问题,「该做什么」,分析如下:累加和是计算⼤于等于当前值的所有元素之和,但是对于⼀个节点来说,父节点和右子树都有可能是⽐它⼤的元素呀?这个没法确定的,我们⼜没有触达⽗节点的指针,所以⼆叉树的通⽤思路在这⾥⽤不了。
我们再来观察BST的中序遍历,正向遍历为升序,那么反向遍历不就是降序吗?反向中序遍历可以降序打印 BST 节点的值,如果维护⼀个外部累加变量 sum,然后把 sum 赋值给 BST 中的每⼀个节点,不就将 BST 转化成累加树了吗?
class Solution:
def convertBST(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
def traverse(node, _sum):
# sum为该节点右边的所有节点的值的总和(所有比该节点大的节点)
if not node:
return _sum
# 累加操作
node.val += traverse(node.right, _sum)
# 传递给左子树
return traverse(node.left, node.val)
traverse(root, 0)
return root
总结
BST 相关的问题,要么利⽤ BST 左⼩右⼤的特性提升算法效率,要么利⽤中序遍历的特性满⾜题⽬的要求。