二叉搜索树中的搜索

标签: 二叉搜索树 二叉树

难度: Easy

给定二叉搜索树(BST)的根节点 root 和一个整数值 val

你需要在 BST 中找到节点值等于 val 的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 null 。

示例 1:

输入:root = [4,2,7,1,3], val = 2
输出:[2,1,3]

示例 2:

输入:root = [4,2,7,1,3], val = 5
输出:[]

提示:

  • 树中节点数在 [1, 5000] 范围内
  • 1 <= Node.val <= 107
  • root 是二叉搜索树
  • 1 <= val <= 107

Submission

运行时间: 68 ms

内存: 17.1 MB

# 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 searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        if root is None:
            return 
        if root.val == val:
            return root
        if root.val > val:
            return self.searchBST(root.left, val)
        if root.val < val:
            return self.searchBST(root.right, val)

Explain

题解采用了递归方法来搜索二叉搜索树(BST)。首先检查当前节点是否为空,若为空,则返回 null。接下来,比较当前节点的值与目标值。如果当前节点的值等于目标值,则返回当前节点,这意味着找到了目标节点,并将以此节点为根的子树作为结果返回。如果目标值小于当前节点的值,递归搜索当前节点的左子树;如果目标值大于当前节点的值,则递归搜索右子树。这个过程一直进行,直到找到目标值或者遍历完树(遇到空节点)。

时间复杂度: O(h),其中 h 是树的高度,最差情况下为 O(n),最好情况下为 O(log n)

空间复杂度: O(h),其中 h 是树的高度,最差情况下为 O(n),最好情况下为 O(log n)

# 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 searchBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
        if root is None:  # 检查当前节点是否为空
            return None  # 空节点,返回 None
        if root.val == val:  # 检查当前节点的值是否等于目标值
            return root  # 相等,返回当前节点作为子树的根
        if root.val > val:  # 如果当前节点值大于目标值
            return self.searchBST(root.left, val)  # 递归搜索左子树
        if root.val < val:  # 如果当前节点值小于目标值
            return self.searchBST(root.right, val)  # 递归搜索右子树

Explore

因为在二叉搜索树(BST)中,所有左子节点的值都小于其父节点的值,而所有右子节点的值都大于其父节点的值。这种结构使得搜索可以高效进行:如果目标值小于当前节点的值,那么目标值必然不会出现在当前节点的右子树中,因此只需要搜索左子树;同样地,如果目标值大于当前节点的值,则目标值不会出现在左子树中,因此只需要搜索右子树。这样的逻辑确保了搜索过程是高效的,不需要检查不相关的部分。

如果目标值不存在于树中,搜索过程最终会达到树的叶节点的子节点(即空节点)。在代码中,每次递归调用首先检查当前节点是否为空(`if root is None`),如果是空的,说明已经到达了树的边界但未找到目标值,因此返回`null`。这种方式自然地处理了目标值不存在的情况,因为搜索路径最终总会遇到空节点。

在普通的BST搜索过程中,存储额外信息如子树的大小不会直接提高搜索效率,因为搜索依赖于比较节点值。但是,这类信息可以在其他操作中提供优势,如在平衡二叉树(如AVL树或红黑树)中维护平衡或在选择操作(找第k小的元素)时。如果要利用子树大小信息来提高搜索效率,可能需要考虑不同的数据结构或算法,如在维护平衡的同时进行搜索,通过控制树的高度来间接提高搜索效率。

在递归搜索中,对于`root`为空的判断是必要的,它属于递归停止的基本条件之一。没有更高效的方法来省略这个检查,因为每次递归都可能达到树的边界。此外,这个检查也是确保程序不会因尝试访问空对象的属性而崩溃的关键。因此,这种方式是最优的,确保了程序的健壮性和正确性。