返回

二叉搜索树实战秘籍:掌握经典解法,上分无忧

后端

二叉搜索树(BST):掌握经典解法,轻松应聘 LeetCode

概述

二叉搜索树(BST)是一种重要的数据结构,在计算机科学中有着广泛的应用。BST 的特点是,每个节点的值都比其左子节点的值大,而比其右子节点的值小。这种结构使得 BST 非常适合用于查找和插入操作,时间复杂度为 O(logn)。

在 LeetCode 面试题中,BST 经常出现。掌握 BST 的经典解法可以帮助你轻松上分。本文将分享 5 个经典问题及其解决方案,包括:

1. 判断 BST 的合法性

2. 计算 BST 中某个范围内的元素和

3. 根据前序遍历结果重建 BST

4. 寻找 BST 中两个节点的最近公共祖先

5. 实现 BST 的插入、删除和查找操作

1. 判断 BST 的合法性

给定一个二叉树,判断它是否是一个 BST。

Java 代码示例:

public boolean isValidBST(TreeNode root) {
    return isValidBST(root, Long.MIN_VALUE, Long.MAX_VALUE);
}

private boolean isValidBST(TreeNode root, long minVal, long maxVal) {
    if (root == null) {
        return true;
    }
    if (root.val <= minVal || root.val >= maxVal) {
        return false;
    }
    return isValidBST(root.left, minVal, root.val) && isValidBST(root.right, root.val, maxVal);
}

2. 计算 BST 中某个范围内的元素和

给定一个 BST,计算 BST 中某个范围内的元素和。

Java 代码示例:

public int rangeSumBST(TreeNode root, int low, int high) {
    if (root == null) {
        return 0;
    }
    int sum = 0;
    if (root.val >= low && root.val <= high) {
        sum += root.val;
    }
    if (root.val > low) {
        sum += rangeSumBST(root.left, low, high);
    }
    if (root.val < high) {
        sum += rangeSumBST(root.right, low, high);
    }
    return sum;
}

3. 根据前序遍历结果重建 BST

给定一个前序遍历的结果,重建 BST。

Java 代码示例:

public TreeNode buildTree(int[] preorder) {
    if (preorder == null || preorder.length == 0) {
        return null;
    }
    int rootVal = preorder[0];
    TreeNode root = new TreeNode(rootVal);
    int leftEndIndex = 0;
    for (int i = 1; i < preorder.length; i++) {
        if (preorder[i] > rootVal) {
            leftEndIndex = i;
            break;
        }
    }
    int[] leftSubtree = Arrays.copyOfRange(preorder, 1, leftEndIndex);
    int[] rightSubtree = Arrays.copyOfRange(preorder, leftEndIndex, preorder.length);
    root.left = buildTree(leftSubtree);
    root.right = buildTree(rightSubtree);
    return root;
}

4. 寻找 BST 中两个节点的最近公共祖先

给定 BST 中两个节点,找到它们的最近公共祖先(LCA)。

Java 代码示例:

public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
    if (root == null || root == p || root == q) {
        return root;
    }
    TreeNode leftLCA = lowestCommonAncestor(root.left, p, q);
    TreeNode rightLCA = lowestCommonAncestor(root.right, p, q);
    if (leftLCA != null && rightLCA != null) {
        return root;
    }
    return leftLCA != null ? leftLCA : rightLCA;
}

5. 实现 BST 的插入、删除和查找操作

Java 代码示例:

public void insert(int val) {
    TreeNode newNode = new TreeNode(val);
    if (root == null) {
        root = newNode;
        return;
    }
    TreeNode curr = root;
    while (true) {
        if (val < curr.val) {
            if (curr.left == null) {
                curr.left = newNode;
                return;
            } else {
                curr = curr.left;
            }
        } else {
            if (curr.right == null) {
                curr.right = newNode;
                return;
            } else {
                curr = curr.right;
            }
        }
    }
}

public void delete(int val) {
    TreeNode curr = root;
    TreeNode parent = null;
    while (curr != null && curr.val != val) {
        parent = curr;
        if (val < curr.val) {
            curr = curr.left;
        } else {
            curr = curr.right;
        }
    }
    if (curr == null) {
        return;
    }
    if (curr.left == null && curr.right == null) {
        if (parent == null) {
            root = null;
        } else {
            if (parent.left == curr) {
                parent.left = null;
            } else {
                parent.right = null;
            }
        }
    } else if (curr.left != null && curr.right == null) {
        if (parent == null) {
            root = curr.left;
        } else {
            if (parent.left == curr) {
                parent.left = curr.left;
            } else {
                parent.right = curr.left;
            }
        }
    } else if (curr.left == null && curr.right != null) {
        if (parent == null) {
            root = curr.right;
        } else {
            if (parent.left == curr) {
                parent.left = curr.right;
            } else {
                parent.right = curr.right;
            }
        }
    } else {
        TreeNode successor = curr.right;
        TreeNode successorParent = curr;
        while (successor.left != null) {
            successorParent = successor;
            successor = successor.left;
        }
        curr.val = successor.val;
        if (successorParent.left == successor) {
            successorParent.left = successor.right;
        } else {
            successorParent.right = successor.right;
        }
    }
}

public TreeNode search(int val) {
    TreeNode curr = root;
    while (curr != null && curr.val != val) {
        if (val < curr.val) {
            curr = curr.left;
        } else {
            curr = curr.right;
        }
    }
    return curr;
}

常见问题解答

1. 什么是二叉搜索树?

二叉搜索树(BST)是一种数据结构,其中每个节点的值都比其左子节点的值大,而比其右子节点的值小。

2. BST 的优点有哪些?

BST 的优点包括快速查找和插入操作,时间复杂度为 O(logn)。

3. BST 在 LeetCode 面试题中有哪些应用?

BST 在 LeetCode 面试题中经常被用来解决各种问题,例如判断 BST 的合法性、计算 BST 中某个范围内的元素和、根据前序遍历结果重建 BST,以及查找 BST 中两个节点的最近公共祖先。

4. 如何判断一个二叉树是否是一个 BST?

可以使用递归方法判断一个二叉树是否是一个 BST。首先,检查根节点是否满足 BST 的性质。然后,递归地检查左子树和右子树是否也是 BST。

5. 如何在 BST 中查找一个节点?

可以在 BST 中使用递归方法查找一个节点。从根节点开始,如果要查找的值等于根节点的值,则返回根节点。如果要查找的值小于根节点的值,则递归地搜索左子树。否则,递归地搜索右子树。