You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用O(nlgn)时间判断二叉树是否为BST?分治法合并设计求助

用分治法判断二叉树是否为BST的思路拆解

嘿,这个问题我之前刚琢磨过,咱们一步步把它理明白~

首先得明确:用分治法判断BST,核心不只是每个子树自己是BST,还要保证左子树的所有节点值都小于当前根,右子树的所有节点值都大于当前根。这意味着递归函数不能只返回「是否是BST」这一个布尔值,得额外带回来子树的最大值和最小值——这就是解决你疑惑的关键。

分治法的核心步骤

咱们把递归过程拆成三部分:

  • 递归处理左子树:得到三个结果:左子树是否为BST、左子树的最小值、左子树的最大值
  • 递归处理右子树:同样得到三个结果:右子树是否为BST、右子树的最小值、右子树的最大值
  • 合并判断(这一步就是你关心的部分):
    1. 左、右子树必须都满足是BST
    2. 当前根的值要大于左子树的最大值(如果左子树存在的话)
    3. 当前根的值要小于右子树的最小值(如果右子树存在的话)
      同时,咱们还要计算出当前子树的最小值(左子树最小值和当前根的较小值)和最大值(右子树最大值和当前根的较大值),返回给上层递归用。

关于时间复杂度的澄清

你提到的递归式 T(n) = 2T(n/2) + O(n) 其实有点小偏差哦。因为这里的合并步骤根本不需要O(n)的时间——每个节点的合并操作都是**O(1)**的:只需要做几次比较和取最值的操作,完全不需要遍历子树。

正确的递归式应该是 T(n) = T(k) + T(n-k-1) + O(1),其中k是左子树的节点数,n-k-1是右子树的节点数。把这个式子展开后,整体时间复杂度就是O(n),因为每个节点只会被递归函数处理一次。

伪代码示例

给你写个简单的伪代码,直观看看怎么实现:

def is_binary_search_tree(root):
    def divide_and_conquer(node):
        # 空树视为合法BST,用无穷大/小占位min和max
        if not node:
            return (True, float('inf'), float('-inf'))
        
        # 递归处理左右子树
        left_valid, left_min, left_max = divide_and_conquer(node.left)
        right_valid, right_min, right_max = divide_and_conquer(node.right)
        
        # 合并判断当前子树是否合法
        current_valid = left_valid and right_valid
        if node.left:
            current_valid = current_valid and (left_max < node.val)
        if node.right:
            current_valid = current_valid and (node.val < right_min)
        
        # 计算当前子树的min和max
        current_min = min(left_min, node.val)
        current_max = max(right_max, node.val)
        
        return (current_valid, current_min, current_max)
    
    return divide_and_conquer(root)[0]

关键总结

  • 分治法的核心是让递归函数返回额外信息(子树的min和max),避免合并时重复遍历子树
  • 每个节点的合并操作都是O(1),整体算法时间复杂度为O(n),完全符合高效要求

内容的提问来源于stack exchange,提问作者Peyman Tahghighi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 06:23:35