二叉搜索树(Binary Search Tree, BST)的定义
二叉搜索树是一种特殊的二叉树,满足以下性质:
-
左子树:所有节点的值小于根节点的值。
-
右子树:所有节点的值大于根节点的值。
-
子树:左右子树也必须是二叉搜索树。
二叉搜索树的中序遍历结果是一个升序数组,因此常用于实现动态集合和查找表。
二叉搜索树的性质
-
查找效率:平均时间复杂度为 ,最坏情况下(退化为链表)为 。
-
插入和删除:平均时间复杂度为 ,最坏情况下为 。
-
动态性:支持高效的动态插入、删除和查找操作。
二叉搜索树常见算法题
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);
}
总结
二叉搜索树是一种高效的数据结构,常用于动态集合和查找表。掌握其基本操作(如查找、插入、删除)和常见算法题(如验证、范围查询、转换等)是算法面试中的必备技能。通过递归和迭代两种方式解决问题,可以更好地理解二叉搜索树的特性。