[LeetCode] 285. Inorder Successor in BST 二叉搜索樹中的中序后繼節點


 

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

The successor of a node p is the node with the smallest key greater than p.val.

 

Example 1:

Input: root = [2,1,3], p = 1 Output: 2 Explanation: 1's in-order successor node is 2. Note that both p and the return value is of TreeNode type. 

Example 2:

Input: root = [5,3,6,2,4,null,null,1], p = 6 Output: null Explanation: There is no in-order successor of the current node, so the answer is null. 

 

Note:

  1. If the given node has no in-order successor in the tree, return null.
  2. It's guaranteed that the values of the tree are unique.

 

這道題讓我們求二叉搜索樹的某個節點的中序后繼節點,那么根據 BST 的性質知道其中序遍歷的結果是有序的,博主最先用的方法是用迭代的中序遍歷方法,然后用一個 bool 型的變量b,初始化為 false,進行中序遍歷,對於遍歷到的節點,首先看如果此時b已經為 true,說明之前遍歷到了p,那么此時返回當前節點,如果b仍為 false,看遍歷到的節點和p是否相同,如果相同,此時將b賦為 true,那么下一個遍歷到的節點就能返回了,參見代碼如下:

 

解法一:

class Solution {
public:
    TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {
        stack<TreeNode*> s;
        bool b = false;
        TreeNode *t = root;
        while (t || !s.empty()) {
            while (t) {
                s.push(t);
                t = t->left;
            }
            t = s.top(); s.pop();
            if (b) return t;
            if (t == p) b = true;
            t = t->right;
        }
        return NULL;
    }
};

 

下面這種方法是用的中序遍歷的遞歸寫法,需要兩個全局變量 pre 和 suc,分別用來記錄祖先節點和后繼節點,初始化將他們都賦為 NULL,然后在進行遞歸中序遍歷時,對於遍歷到的節點,首先看 pre 和p是否相同,如果相同,則 suc 賦為當前節點,然后將 pre 賦為 root,那么在遍歷下一個節點時,pre 就起到記錄上一個節點的作用,參見代碼如下:

 

解法二:

class Solution {
public:
    TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {
        if (!p) return NULL;
        inorder(root, p);
        return suc;
    }
    void inorder(TreeNode *root, TreeNode *p) {
        if (!root) return;
        inorder(root->left, p);
        if (pre == p) suc = root;
        pre = root;
        inorder(root->right, p);
    }
private:
    TreeNode *pre = NULL, *suc = NULL;
};

 

再來看一種更簡單的方法,這種方法充分地利用到了 BST 的性質,首先看根節點值和p節點值的大小,如果根節點值大,說明p節點肯定在左子樹中,那么此時先將 res 賦為 root,然后 root 移到其左子節點,循環的條件是 root 存在,再比較此時 root 值和p節點值的大小,如果還是 root 值大,重復上面的操作,如果p節點值,那么將 root 移到其右子節點,這樣當 root 為空時,res 指向的就是p的后繼節點,參見代碼如下:

 

解法三:

class Solution {
public:
    TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {
        TreeNode *res = NULL;
        while (root) {
            if (root->val > p->val) {
                res = root;
                root = root->left;
            } else root = root->right;
        }
        return res;
    }
};

 

上面那種方法也可以寫成遞歸形式,寫法也比較簡潔,但是需要把思路理清,當根節點值小於等於p節點值,說明p的后繼節點一定在右子樹中,所以對右子節點遞歸調用此函數,如果根節點值大於p節點值,那么有可能根節點就是p的后繼節點,或者左子樹中的某個節點是p的后繼節點,所以先對左子節點遞歸調用此函數,如果返回空,說明根節點是后繼節點,返回即可,如果不為空,則將那個節點返回,參見代碼如下:

 

解法四:

class Solution {
public:
    TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {
        if (!root) return NULL;
        if (root->val <= p->val) {
            return inorderSuccessor(root->right, p);
        } else {
            TreeNode *left = inorderSuccessor(root->left, p);
            return left ? left : root;
        }
    }
};

 

Github 同步地址:

https://github.com/grandyang/leetcode/issues/285

 

類似題目:

Binary Search Tree Iterator

Binary Tree Inorder Traversal

Inorder Successor in BST II

 

參考資料:

https://leetcode.com/problems/inorder-successor-in-bst/

https://leetcode.com/problems/inorder-successor-in-bst/discuss/72653/Share-my-Java-recursive-solution

https://leetcode.com/problems/inorder-successor-in-bst/discuss/72662/*Java*-5ms-short-code-with-explanations

https://leetcode.com/problems/inorder-successor-in-bst/discuss/72656/JavaPython-solution-O(h)-time-and-O(1)-space-iterative

 

LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM