[刷题]Inorder Successor in BST

本文介绍了一种在大型已排序数组中查找特定目标值的有效算法。通过预先优化搜索范围,结合二分查找技术,该算法能在O(log n)的时间复杂度内完成查找,并返回目标值在数组中的位置。

[LintCode]Inorder Successor in BST

public class Solution {
    /**
     * @param A: An integer array
     * @param target: An integer
     * @return : An integer which is the index of the target number
     */
    public int searchBigSortedArray(int[] A, int target) {
        // 2015-10-13
        if (A == null || A.length == 0) {
            return -1;
        }
        
        // 优化end以缩小搜索范围
        int end = 0;
        while (end < A.length -1 && A[end] < target) {
            end = end * 2 + 1;
            if (end >= A.length) {
                end = A.length - 1;
            }
        }
        
        // 二分搜索
        int start = 0;
        while (start < end - 1) {
            int mid = start + (end - start) / 2; 
            if (A[mid] >= target) {
                end = mid;
            } else {
                start = mid;
            }
        }
        if (A[start] == target) {
            return start;
        }
        if (A[end] == target) {
            return end;
        }
        return -1;
    }
}


#include <iostream>#include <iostream>using namespace std;struct TreeNode {int val;TreeNode *left;TreeNode *right;TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}};class BST {public:TreeNode* root;BST() : root(nullptr) {}void insert(int val) {TreeNode* newNode = new TreeNode(val);if (!root) {root = newNode;return;}TreeNode* curr = root;while (true) {if (val < curr->val) {if (curr->left)curr = curr->left;else {curr->left = newNode;break;}}else if (val > curr->val) {if (curr->right)curr = curr->right;else {curr->right = newNode;break;}}else {delete newNode; return;}}}TreeNode* findMin(TreeNode* node) {while (node->left) node = node->left;return node;}TreeNode* remove(TreeNode* node, int val) {if (!node) return nullptr;if (val < node->val) {node->left = remove(node->left, val);}else if (val > node->val) {node->right = remove(node->right, val);}else {if (!node->left) {TreeNode* temp = node->right;delete node;return temp;}else if (!node->right) {TreeNode* temp = node->left;delete node;return temp;}else {TreeNode* successor = findMin(node->right);node->val = successor->val;node->right = remove(node->right, successor->val);}}return node;}void inorder(TreeNode* node) {if (node) {inorder(node->left);cout << node->val << " ";inorder(node->right);}}void remove(int val) {root = remove(root, val);}void printInorder() {inorder(root);cout << endl;}};int main() {BST bst;int arr[] = { 4, 9, 0, 1, 8, 6, 3, 5, 2, 7 };int n = sizeof(arr) / sizeof(arr[0]);for (int i = 0; i < n; ++i) {bst.insert(arr[i]);}cout << "初始中序遍历: ";bst.printInorder();// 删除关键字为4的节点bst.remove(4);cout << "删除4后中序遍历: ";bst.printInorder();// 删除关键字为5的节点bst.remove(5);cout << "删除5后中序遍历: ";bst.printInorder();return 0;} 对此代码进行详细解释
最新发布
11-02
二叉搜索树(Binary Search Tree,简称 BST)是一种重要的基础数据结构,它的核心在于遵循一组简单的**排序规则**,使得数据可以高效地进行查找、插入和删除。 --- ## ✅ 一、BST 的基本规则(性质) 一棵合法的二叉搜索树必须满足以下条件: ### 🔹 1. 左子树所有节点值 < 根节点值 ### 🔹 2. 右子树所有节点值 > 根节点值 ### 🔹 3. 左右子树也分别是二叉搜索树(递归定义) ### 🔹 4. 没有重复值(通常约定,也可允许左 ≤ 或右 ≥,但需统一) > 📌 数学表达: > 对于任意节点 `x`: > - 若 `y` 是 `x` 的左子树中的节点,则 `y.val < x.val` > - 若 `y` 是 `x` 的右子树中的节点,则 `y.val > x.val` --- ## ✅ 二、示例说明 ```text 50 / \ 30 70 / \ / \ 20 40 60 80 ✔️ 合法 BST:每个左子 < 父 < 右子 ``` 反例 ❌: ```text 50 / \ 30 70 / \ 20 60 ← 60 > 50,但它在左子树中 → 违反 BST 规则! ``` --- ## ✅ 三、BST 的基本操作与代码实现(Python) 我们来实现一个完整的 BST 类,包含:插入、查找、删除。 ### 1. 节点定义 ```python class TreeNode: def __init__(self, val=0): self.val = val self.left = None self.right = None ``` --- ### 2. 插入(Insert) 从根开始比较,小于往左走,大于往右走,直到空位插入。 ```python def insert(root, val): if not root: return TreeNode(val) if val < root.val: root.left = insert(root.left, val) elif val > root.val: root.right = insert(root.right, val) # 如果相等,不插入(去重) return root ``` 📌 使用方式: ```python root = None for v in [50, 30, 70, 20, 40, 60, 80]: root = insert(root, v) ``` --- ### 3. 查找(Search) 类似插入,按大小关系决定方向。 ```python def search(root, val): if not root or root.val == val: return root if val < root.val: return search(root.left, val) else: return search(root.right, val) ``` ✅ 返回找到的节点,否则返回 `None` --- ### 4. 删除(Delete)—— 最复杂的操作 分为三种情况: | 情况 | 处理方式 | |------|----------| | ① 删除叶节点 | 直接删除 | | ② 删除只有一个孩子的节点 | 让父节点指向其孩子 | | ③ 删除有两个孩子的节点 | 找到**中序后继**(右子树最小值)或**前驱**(左子树最大值),替换值后再删掉那个节点 | ```python def delete(root, val): if not root: return root if val < root.val: root.left = delete(root.left, val) elif val > root.val: root.right = delete(root.right, val) else: # 找到要删除的节点 # 情况① 和 ②:有一个或没有孩子 if not root.left: return root.right elif not root.right: return root.left # 情况③:有两个孩子 # 找右子树中的最小值(中序后继) successor = find_min(root.right) root.val = successor.val root.right = delete(root.right, successor.val) return root def find_min(node): while node.left: node = node.left return node ``` --- ### 5. 遍历(验证是否为 BST) 常用中序遍历(In-order Traversal),结果应为**升序序列** ```python def inorder(root, res): if root: inorder(root.left, res) res.append(root.val) inorder(root.right, res) # 检查是否为有效 BST def is_valid_bst(root): res = [] inorder(root, res) return all(res[i] < res[i+1] for i in range(len(res)-1)) ``` --- ## ✅ 四、BST 的优缺点 | 优点 | 缺点 | |------|------| | ✅ 支持动态插入/删除 | ❌ 最坏情况退化成链表(O(n)) | | ✅ 查找平均 O(log n)(平衡时) | ❌ 需要额外机制保持平衡(如 AVL、红黑树) | | ✅ 支持范围查询、前驱后继、排名等 | ❌ 不支持随机访问 | | ✅ 实现简单直观 | ❌ 重复值处理需特别设计 | --- ## ✅ 五、BST 的典型应用场景 | 场景 | 说明 | |------|------| | 数据库索引 | B+树是BST思想的扩展 | | 文件系统 | 层次结构管理 | | 动态集合管理 | 如集合、映射容器 | | Top K 查询 | 利用中序遍历获取有序结果 | | 前驱/后继查找 | 如“找比x小的最大数” | --- ## ✅ 六、常见变种与改进 原始 BST 有个致命问:**如果插入有序数据,会退化成链表** 例如插入 `[1,2,3,4,5]` 得到: ```text 1 \ 2 \ 3 \ 4 \ 5 → 高度 = n,查找 O(n) ``` 为此引入了各种**自平衡 BST**: | 名称 | 特点 | |------|------| | AVL 树 | 严格平衡(左右高度差≤1),查询最快 | | 红黑树 | 近似平衡,插入删除更快,STL 使用 | | Splay 树 | 自适应,热点数据靠近根 | | Treap | 随机优先级 + BST,期望 O(log n) | | 跳表 | 非树结构,但功能类似,Redis 使用 | --- ## ✅ 七、总结一句话: > **BST 的核心规则是:“左小右大”,即每个节点的左子树所有值都小于它,右子树所有值都大于它。这一简单规则赋予了 BST 有序性和高效的查找能力,但为了防止退化,实际应用中常使用红黑树、AVL 树等自平衡版本。** ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值