算法中的二叉搜索树

13 阅读3分钟

二叉搜索树(Binary Search Tree, BST)的定义

二叉搜索树是一种特殊的二叉树,满足以下性质:

  1. 左子树:所有节点的值小于根节点的值。

  2. 右子树:所有节点的值大于根节点的值。

  3. 子树:左右子树也必须是二叉搜索树。

二叉搜索树的中序遍历结果是一个升序数组,因此常用于实现动态集合和查找表。


二叉搜索树的性质

  1. 查找效率:平均时间复杂度为 ,最坏情况下(退化为链表)为 。

  2. 插入和删除:平均时间复杂度为 ,最坏情况下为 。

  3. 动态性:支持高效的动态插入、删除和查找操作。


二叉搜索树常见算法题

1. 验证二叉搜索树

题目:给定一个二叉树,判断它是否是有效的二叉搜索树。
示例

输入:
    2
   / \
  1   3
输出:true

解法

function isValidBST(root: TreeNode | null): boolean {
  function helper(node: TreeNode | null, lower: number, upper: number): boolean {
    if (!node) return true;
    if (node.val <= lower || node.val >= upper) return false;
    return helper(node.left, lower, node.val) && helper(node.right, node.val, upper);
  }
  return helper(root, -Infinity, Infinity);
}

2. 二叉搜索树的查找

题目:给定一个二叉搜索树和一个值,判断该值是否在树中。
示例

输入:
    4
   / \
  2   7
 / \
1   3
查找值:2
输出:true

解法

function searchBST(root: TreeNode | null, val: number): TreeNode | null {
  if (!root || root.val === val) return root;
  return val < root.val ? searchBST(root.left, val) : searchBST(root.right, val);
}

3. 二叉搜索树的插入

题目:给定一个二叉搜索树和一个值,将该值插入树中。
示例

输入:
    4
   / \
  2   7
 / \
1   3
插入值:5
输出:
    4
   / \
  2   7
 / \ /
1  3 5

解法

function insertIntoBST(root: TreeNode | null, val: number): TreeNode | null {
  if (!root) return new TreeNode(val);
  if (val < root.val) root.left = insertIntoBST(root.left, val);
  else root.right = insertIntoBST(root.right, val);
  return root;
}

4. 二叉搜索树的删除

题目:给定一个二叉搜索树和一个值,删除树中对应的节点。
示例

输入:
    5
   / \
  3   6
 / \   \
2   4   7
删除值:3
输出:
    5
   / \
  4   6
 /     \
2       7

解法

function deleteNode(root: TreeNode | null, key: number): TreeNode | null {
  if (!root) return null;
  if (key < root.val) root.left = deleteNode(root.left, key);
  else if (key > root.val) root.right = deleteNode(root.right, key);
  else {
    if (!root.left) return root.right;
    if (!root.right) return root.left;
    const minNode = findMin(root.right);
    root.val = minNode.val;
    root.right = deleteNode(root.right, minNode.val);
  }
  return root;
}

function findMin(node: TreeNode): TreeNode {
  while (node.left) node = node.left;
  return node;
}

5. 二叉搜索树的中序遍历

题目:给定一个二叉搜索树,返回其中序遍历结果。
示例

输入:
    4
   / \
  2   5
 / \   \
1   3   6
输出:[1, 2, 3, 4, 5, 6]

解法

function inorderTraversal(root: TreeNode | null): number[] {
  const result: number[] = [];
  function traverse(node: TreeNode | null) {
    if (!node) return;
    traverse(node.left);
    result.push(node.val);
    traverse(node.right);
  }
  traverse(root);
  return result;
}

6. 二叉搜索树的范围和

题目:给定一个二叉搜索树和范围 [low, high],返回所有节点值在范围内的和。
示例

输入:
    10
   /  \
  5    15
 / \    \
3   7    18
范围:[7, 15]
输出:32

解法

function rangeSumBST(root: TreeNode | null, low: number, high: number): number {
  if (!root) return 0;
  if (root.val < low) return rangeSumBST(root.right, low, high);
  if (root.val > high) return rangeSumBST(root.left, low, high);
  return root.val + rangeSumBST(root.left, low, high) + rangeSumBST(root.right, low, high);
}

7. 将有序数组转换为二叉搜索树

题目:给定一个升序数组,将其转换为高度平衡的二叉搜索树。
示例

输入:[-10, -3, 0, 5, 9]
输出:
      0
     / \
   -3   9
   /   /
 -10  5

解法

function sortedArrayToBST(nums: number[]): TreeNode | null {
  function helper(left: number, right: number): TreeNode | null {
    if (left > right) return null;
    const mid = Math.floor((left + right) / 2);
    const root = new TreeNode(nums[mid]);
    root.left = helper(left, mid - 1);
    root.right = helper(mid + 1, right);
    return root;
  }
  return helper(0, nums.length - 1);
}

总结

二叉搜索树是一种高效的数据结构,常用于动态集合和查找表。掌握其基本操作(如查找、插入、删除)和常见算法题(如验证、范围查询、转换等)是算法面试中的必备技能。通过递归和迭代两种方式解决问题,可以更好地理解二叉搜索树的特性。