二叉搜索树(Binary Search Tree, BST)是面试大厂时常考察的重要数据结构之一。它是一种特殊的二叉树,具有以下性质:
- 节点的左子树只包含小于当前节点的数。
- 节点的右子树只包含大于当前节点的数。
- 左右子树也必须分别为二叉搜索树。
- 没有键值相等的节点(这一点可能根据实现略有不同)。
掌握以下关于二叉搜索树的知识点,对于面试大厂的准备至关重要:
1. 二叉搜索树的基本操作
- 插入:遵循二叉搜索树的性质,找到合适的位置插入新节点。
- 查找:从根节点开始,利用二叉搜索树的性质查找元素。
- 删除:删除操作稍微复杂,分为三种情况:删除的节点没有子节点、有一个子节点、有两个子节点。
- 遍历:中序遍历可以得到有序的元素序列,前序和后序遍历用于其他特定的应用场景。
2. 平衡二叉搜索树
- AVL树:是最早的自平衡二叉搜索树之一,通过旋转操作保持树的平衡,即任一节点的两个子树的高度最大差别为一。
- 红黑树:是一种自平衡二叉搜索树,通过节点着色及旋转操作保持树的近似平衡,广泛应用于Java的
TreeMap
和TreeSet
。
3. 二叉搜索树的应用
- 实现集合和映射抽象数据类型:如Java中的
TreeMap
和TreeSet
。 - 数据库索引:数据库索引经常采用某种形式的二叉搜索树,如B树和B+树。
4. 复杂度分析
- 时间复杂度:在平衡的二叉搜索树中,查找、插入和删除操作的平均时间复杂度为O(log n),在最坏的情况下(树退化为链表)为O(n)。
- 空间复杂度:O(n),其中n是树中节点的数量。
示例代码:二叉搜索树的插入操作
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {
val = x;
}
}
public class BinarySearchTree {
public TreeNode insert(TreeNode root, int val) {
if (root == null) {
root = new TreeNode(val);
return root;
}
if (val < root.val) {
root.left = insert(root.left, val);
} else if (val > root.val) {
root.right = insert(root.right, val);
}
return root;
}
}
这段Java代码演示了在二叉搜索树中插入新节点的基本逻辑。掌握这些基本概念和操作是面试准备的重要一环,同时也要注意平衡二叉搜索树的特性和应用,因为它们在实际应用中非常重要,尤其是在性能敏感的系统中。针对二叉搜索树(BST),这里提供三个面试题目,包括问题描述和Java源码解答。这些题目旨在考察你对BST的理解,以及在实际问题中应用BST的能力。
题目1:验证二叉搜索树
题目描述:
给定一个二叉树,判断其是否是一个有效的二叉搜索树。假设一个二叉搜索树具有如下特征:
- 节点的左子树只包含小于当前节点的数。
- 节点的右子树只包含大于当前节点的数。
- 所有左子树和右子树自身必须也是二叉搜索树。
示例代码:
public class ValidateBST {
public boolean isValidBST(TreeNode root) {
return validate(root, Long.MIN_VALUE, Long.MAX_VALUE);
}
private boolean validate(TreeNode node, long low, long high) {
if (node == null) {
return true;
}
if (node.val <= low || node.val >= high) {
return false;
}
return validate(node.left, low, node.val) && validate(node.right, node.val, high);
}
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
}
题目2:二叉搜索树中第K小的元素
题目描述:
给定一个二叉搜索树,编写一个函数 kthSmallest
来查找其中第 K 小的元素。
示例代码:
public class KthSmallestElementInBST {
public int kthSmallest(TreeNode root, int k) {
ArrayList<Integer> nums = inorder(root, new ArrayList<Integer>());
return nums.get(k - 1);
}
public ArrayList<Integer> inorder(TreeNode root, ArrayList<Integer> arr) {
if (root == null) {
return arr;
}
inorder(root.left, arr);
arr.add(root.val);
inorder(root.right, arr);
return arr;
}
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
}
题目3:将有序数组转换为二叉搜索树
题目描述:
给你一个整数数组 nums
,其中元素已经按升序排列,请你将其转换为一棵高度平衡二叉搜索树。
高度平衡二叉树是指一个二叉树每个节点的左右两个子树的高度差的绝对值不超过 1。
示例代码:
public class SortedArrayToBST {
public TreeNode sortedArrayToBST(int[] nums) {
return buildBST(nums, 0, nums.length - 1);
}
private TreeNode buildBST(int[] nums, int left, int right) {
if (left > right) {
return null;
}
int mid = left + (right - left) / 2;
TreeNode node = new TreeNode(nums[mid]);
node.left = buildBST(nums, left, mid - 1);
node.right = buildBST(nums, mid + 1, right);
return node;
}
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
}
通过这些题目及其解答,你不仅可以展示你对二叉搜索树的理解和编程能力,还能证明你能够应用这些知识来解决实际问题。在准备面试时,确保你理解每道题目的解决方案,并尝试自己编写代码,以加深理解和记忆。