[Leetcode] 285. Inorder Successor in BST 解题报告

BST中序后继节点寻找的高效解法
本文介绍了如何在二叉搜索树(BST)中找到指定节点的中序后继节点。提供了两种解决方案,包括一个O(n)时间复杂度的方法和一个优化后的O(logn)方法。优化后的算法通过判断目标节点与根节点的值关系,缩小搜索范围,降低了空间复杂度至O(1)。

题目

Given a binary search tree and a node in it, find the in-order successor of that node in the BST.

Note: If the given node has no in-order successor in the tree, return null.

思路

1、O(n)的解法:最开始容易想到的思路就是直接进行中序遍历。一旦发现我们遍历到的当前结点的前驱是p,就更新结果。这种思路的时间复杂度是O(n),空间复杂度是O(1)。
2、O(logn)的解法:我开始的想法是分两种情况:1)p的右子树不为空,那么p的后继结点就是p的右子树上的最左侧的结点;2)p的右子树为空,那么p的后继结点就是它的祖先中第一个比它值大的结点(也有可能为空),在这种情况下,需要开辟一个栈空间来存贮p的所有祖先结点。这种思路可以把时间复杂度可以降低到O(logn),但是空间复杂度却是O(logn)。后来看到下面这个更巧妙的算法:如果p的值比root的值大或者p就是root,那么p的后继不可能出现在root以及root的左子树上,所以我们只需要在root的右子树上继续找;如果p的值比root的值小,那么p的直接后继既有可能是root,也有可能是root的左子树上的某个结点,此时需要更新答案,并且在root的左子树上继续找。这种思路完美地统一处理了p的右子树是否为空两种情况,并且将空间复杂度降低到了O(1)。

代码

1、O(n)的解法:

/** 
 * Definition for a binary tree node. 
 * struct TreeNode { 
 *     int val; 
 *     TreeNode *left; 
 *     TreeNode *right; 
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {} 
 * }; 
 */  
class Solution {  
public:  
    TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {  
        if (!root) {  
            return NULL;  
        }  
        inorderSuccessor(root->left, p);  
        if (pre == p) {  
            ret = root;  
        }  
        pre = root;  
        inorderSuccessor(root->right, p);  
        return ret;  
    }  
private:  
    TreeNode *pre = NULL, *ret = NULL;  
};
2、O(logn)的解法:

/** 
 * Definition for a binary tree node. 
 * struct TreeNode { 
 *     int val; 
 *     TreeNode *left; 
 *     TreeNode *right; 
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {} 
 * }; 
 */  
class Solution {  
public:  
    TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {  
        if (root == NULL || p == NULL) {  
            return NULL;  
        }  
        TreeNode *ret = NULL;  
        while (root) {  
            if (p->val < root->val) {  
                ret = root;  
                root = root->left;  
            }  
            else {  
                root = root->right;  
            }  
        }  
        return ret;  
    }  
}; 
### Successor 的定义与用法 在编程领域,`successor` 通常指代某个对象、节点或状态的“后继者”。具体含义和用法取决于上下文环境。以下是 `successor` 在不同场景中的定义与用法: #### 1. 数据结构中的 Successor 在数据结构中,`successor` 常用于描述一个节点的直接后继节点。例如,在二叉搜索树(Binary Search Tree, BST)中,某个节点的 successor 是其右子树中最左侧的节点[^1]。如果该节点没有右子树,则需要沿着父节点路径向上查找,直到找到第一个值大于当前节点的祖先节点。 ```python def find_successor(node): if node is None: return None # 如果有右子树,successor 是右子树中最左节点 if node.right: current = node.right while current.left: current = current.left return current # 如果没有右子树,则沿父节点路径向上查找 ancestor = node.parent child = node while ancestor and child == ancestor.right: child = ancestor ancestor = ancestor.parent return ancestor ``` #### 2. 责任链模式中的 Successor 在责任链设计模式中,`successor` 表示处理请求的下一个对象。每个对象都有一个指向其后继者的引用,并将请求沿着链传递给下一个处理器,直到某个处理器能够处理该请求为止[^3]。 ```java abstract class Handler { protected Handler successor; public void setSuccessor(Handler successor) { this.successor = successor; } public abstract void handleRequest(int request); } class ConcreteHandlerA extends Handler { @Override public void handleRequest(int request) { if (request >= 0 && request < 10) { System.out.println("ConcreteHandlerA handled request " + request); } else if (successor != null) { successor.handleRequest(request); } } } class ConcreteHandlerB extends Handler { @Override public void handleRequest(int request) { if (request >= 10 && request < 20) { System.out.println("ConcreteHandlerB handled request " + request); } else if (successor != null) { successor.handleRequest(request); } } } ``` #### 3. 接口实现中的 Successor 在接口设计中,`successor` 可以表示一种逻辑上的继承关系或行为扩展。通过实现接口,类可以定义自己的行为,同时遵循接口的规范[^2]。虽然接口本身不涉及 `successor` 的具体定义,但在某些框架中,接口可能被用来描述某种顺序或链条关系。 ```java interface ChainElement { void setNext(ChainElement successor); void process(Request request); } class Authentication implements ChainElement { private ChainElement successor; @Override public void setNext(ChainElement successor) { this.successor = successor; } @Override public void process(Request request) { if (request.isAuthenticated()) { System.out.println("User is authenticated."); if (successor != null) { successor.process(request); } } else { System.out.println("Authentication failed."); } } } ``` ### 总结 `Successor` 的定义和用法因上下文而异。在数据结构中,它通常指代节点的后继;在责任链模式中,它是请求传递链中的下一个处理器;在接口实现中,它可以表示逻辑上的继承或行为扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值