Find the Inorder Successor in a Binary Search Tree
Problem and examples
Given a binary search tree (BST) and a node p in it, find the inorder successor of that node. The inorder successor of a node is the node with the smallest key greater than p.val.
Note: It is guaranteed that the given node p exists in the tree. However, the successor might or might not exist.
| Input Tree | Target Node (p) | Inorder Successor | Description |
|---|---|---|---|
| [20, 10, 30, 5, 15, 25, 35] | 15 | 20 | Inorder successor of 15 is 20, the lowest ancestor for which 15 is in left subtree. |
| [20, 10, 30, 5, 15, 25, 35] | 10 | 15 | Successor is leftmost node in 10's right subtree: 15. |
| [20, 10, 30, 5, 15, 25, 35] | 30 | 35 | 30 has a right child, and its leftmost node is 35 — the inorder successor. |
| [20, 10, 30, 5, 15, 25, 35] | 35 | null | 35 is the rightmost node; it has no inorder successor. |
| [20, 10, null, 5, 15] | 5 | 10 | 5 has no right child. Successor is the lowest ancestor for which 5 lies in the left subtree — 10. |
| [8, 3, 10, 1, 6, null, 14, null, null, 4, 7, 13] | 6 | 7 | 6 has right child 7 → it's the inorder successor. |
How it works
Understanding the Problem
We are given a Binary Search Tree (BST) and a node p. Our goal is to find the inorder successor of this node. An inorder successor is the node that comes immediately after p in the inorder traversal of the tree.
In an inorder traversal of a BST, we visit nodes in ascending order: left subtree → current node → right subtree. So, the inorder successor of a node p is the node with the smallest key greater than p.val.
Step-by-Step Solution with Example
step 1: Identify if node p has a right child
If p has a right child, then its inorder successor will be the leftmost node in the right subtree. This is because we go right once, and then as left as possible to find the next smallest value.
Example: Consider a BST: [4, 2, 6, null, 3, 5, 7]. If p = 4, since 4 has a right child (6), we go to 6, and then go left to find 5. So, the inorder successor is 5.
step 2: Handle the case when node p has no right child
If p does not have a right child, then we have to look at its ancestors. Specifically, we look for the lowest ancestor for which p is in its left subtree. This ancestor will be the next node in the inorder traversal.
We start from the root and simulate the traversal path to p. During this path, if we ever move left, we store the current node as a potential successor. If we move right, we do not update the successor.
Example: For the same BST, if p = 5, it has no right child. Starting from root (4), we move right to 6, then left to 5. Since we moved left from 6 to 5, 6 becomes the successor.
step 3: Account for edge case where p is the largest node
If p is the largest node in the tree, it will not have a successor. There is no node with a value greater than p, so the result should be null.
Example: If p = 7 in the same BST, 7 is the largest. There is no node after 7 in inorder traversal, so the answer is null.
step 4: Traverse and return the stored successor
We either return the leftmost node in the right subtree (step 1), or the stored ancestor (step 2). If neither exists, we return null.
Edge Cases
Tree is empty
If the BST is empty, there are no nodes to process. Return null.
Node p is null
If the input node is null, there’s no way to find a successor. Return null.
Tree has only one node
If the tree contains just one node and that node is p, there is no successor to find. Return null.
Node p is not present in the tree
This depends on the implementation — either you check if p exists in the tree or you assume it does. If it doesn’t exist, the answer should be null or an error should be raised depending on requirements.
Finally
Finding the inorder successor in a BST is an important operation and relies on understanding tree traversal and BST properties. By breaking the problem into two main scenarios (right child exists vs. no right child), and walking through intuitive examples, we can confidently solve this problem. Always remember to include boundary conditions like null nodes or the largest element to make your solution robust.
- Given a binary search tree (BST) and a target node
p. - If
p.rightexists, the inorder successor is the leftmost node in the right subtree. - If
p.rightdoes not exist, initializesuccessor = nulland traverse the tree starting from the root: - While traversing, if
p.val < current.val, updatesuccessorto the current node and move tocurrent.left; otherwise, move tocurrent.right. - After the traversal, the recorded
successoris the inorder successor ofp.
Implementation and efficiency
C implementation
#include <stdio.h>
#include <stdlib.h>
typedef struct TreeNode {
int val;
struct TreeNode *left, *right;
} TreeNode;
TreeNode* createNode(int val) {
TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode));
node->val = val;
node->left = node->right = NULL;
return node;
}
TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {
if (p->right) {
TreeNode* curr = p->right;
while (curr->left) curr = curr->left;
return curr;
}
TreeNode* successor = NULL;
while (root) {
if (p->val < root->val) {
successor = root;
root = root->left;
} else {
root = root->right;
}
}
return successor;
}
int main() {
TreeNode* root = createNode(5);
root->left = createNode(3);
root->right = createNode(7);
root->left->left = createNode(2);
root->left->right = createNode(4);
root->right->right = createNode(8);
TreeNode* p = root->left; // Node with value 3
TreeNode* succ = inorderSuccessor(root, p);
printf("%d\n", succ ? succ->val : -1);
return 0;
}C++ implementation
#include <iostream>
using namespace std;
struct TreeNode {
int val;
TreeNode *left, *right;
TreeNode(int x): val(x), left(nullptr), right(nullptr) {}
};
TreeNode* inorderSuccessor(TreeNode* root, TreeNode* p) {
if (p->right) {
TreeNode* curr = p->right;
while (curr->left) curr = curr->left;
return curr;
}
TreeNode* successor = nullptr;
while (root) {
if (p->val < root->val) {
successor = root;
root = root->left;
} else {
root = root->right;
}
}
return successor;
}
int main() {
TreeNode* root = new TreeNode(5);
root->left = new TreeNode(3);
root->right = new TreeNode(7);
root->left->left = new TreeNode(2);
root->left->right = new TreeNode(4);
root->right->right = new TreeNode(8);
TreeNode* p = root->left; // Node with value 3
TreeNode* succ = inorderSuccessor(root, p);
cout << (succ ? succ->val : -1) << endl;
return 0;
}Python implementation
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def inorderSuccessor(root, p):
if p.right:
curr = p.right
while curr.left:
curr = curr.left
return curr
successor = None
while root:
if p.val < root.val:
successor = root
root = root.left
else:
root = root.right
return successor
if __name__ == '__main__':
root = TreeNode(5,
TreeNode(3, TreeNode(2), TreeNode(4)),
TreeNode(7, None, TreeNode(8)))
p = root.left # Node with value 3
successor = inorderSuccessor(root, p)
print(successor.val if successor else None)Java implementation
class TreeNode {
int val;
TreeNode left, right;
TreeNode(int x) { val = x; }
}
public class InorderSuccessorBST {
public TreeNode inorderSuccessor(TreeNode root, TreeNode p) {
if (p.right != null) {
TreeNode curr = p.right;
while (curr.left != null) {
curr = curr.left;
}
return curr;
}
TreeNode successor = null;
while (root != null) {
if (p.val < root.val) {
successor = root;
root = root.left;
} else {
root = root.right;
}
}
return successor;
}
public static void main(String[] args) {
TreeNode root = new TreeNode(5);
root.left = new TreeNode(3);
root.right = new TreeNode(7);
root.left.left = new TreeNode(2);
root.left.right = new TreeNode(4);
root.right.right = new TreeNode(8);
InorderSuccessorBST sol = new InorderSuccessorBST();
TreeNode p = root.left; // Node with value 3
TreeNode successor = sol.inorderSuccessor(root, p);
System.out.println(successor != null ? successor.val : "null");
}
}JavaScript implementation
class TreeNode {
constructor(val, left = null, right = null) {
this.val = val;
this.left = left;
this.right = right;
}
}
function inorderSuccessor(root, p) {
if (p.right) {
let curr = p.right;
while (curr.left) curr = curr.left;
return curr;
}
let successor = null;
while (root) {
if (p.val < root.val) {
successor = root;
root = root.left;
} else {
root = root.right;
}
}
return successor;
}
const root = new TreeNode(5,
new TreeNode(3, new TreeNode(2), new TreeNode(4)),
new TreeNode(7, null, new TreeNode(8)));
const p = root.left;
const successor = inorderSuccessor(root, p);
console.log(successor ? successor.val : null);Go implementation
package main
import (
"fmt"
)
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
func inorderSuccessor(root, p *TreeNode) *TreeNode {
if p.Right != nil {
curr := p.Right
for curr.Left != nil {
curr = curr.Left
}
return curr
}
var successor *TreeNode
for root != nil {
if p.Val < root.Val {
successor = root
root = root.Left
} else {
root = root.Right
}
}
return successor
}
func main() {
root := &TreeNode{5,
&TreeNode{3, &TreeNode{2, nil, nil}, &TreeNode{4, nil, nil}},
&TreeNode{7, nil, &TreeNode{8, nil, nil}}}
p := root.Left
succ := inorderSuccessor(root, p)
if succ != nil {
fmt.Println(succ.Val)
} else {
fmt.Println("null")
}
}Rust implementation
struct TreeNode {
val: i32,
left: Option<Box<TreeNode>>,
right: Option<Box<TreeNode>>,
}
fn inorder_successor(mut root: Option<&Box<TreeNode>>, p_val: i32) -> Option<i32> {
let mut successor = None;
while let Some(node) = root {
if p_val < node.val {
successor = Some(node.val);
root = node.left.as_ref();
} else {
root = node.right.as_ref();
}
}
successor
}
fn main() {
let root = Box::new(TreeNode {
val: 5,
left: Some(Box::new(TreeNode {
val: 3,
left: Some(Box::new(TreeNode { val: 2, left: None, right: None })),
right: Some(Box::new(TreeNode { val: 4, left: None, right: None }))
})),
right: Some(Box::new(TreeNode {
val: 7,
left: None,
right: Some(Box::new(TreeNode { val: 8, left: None, right: None }))
})),
});
let result = inorder_successor(Some(&root), 3);
println!("{}", result.unwrap_or(-1));
}Kotlin implementation
class TreeNode(var val_: Int) {
var left: TreeNode? = null
var right: TreeNode? = null
}
fun inorderSuccessor(root: TreeNode?, p: TreeNode): TreeNode? {
if (p.right != null) {
var curr = p.right
while (curr?.left != null) {
curr = curr.left
}
return curr
}
var curr = root
var successor: TreeNode? = null
while (curr != null) {
if (p.val_ < curr.val_) {
successor = curr
curr = curr.left
} else {
curr = curr.right
}
}
return successor
}
fun main() {
val root = TreeNode(5)
root.left = TreeNode(3)
root.right = TreeNode(7)
root.left?.left = TreeNode(2)
root.left?.right = TreeNode(4)
root.right?.right = TreeNode(8)
val p = root.left!!
val succ = inorderSuccessor(root, p)
println(succ?.val_ ?: "null")
}Swift implementation
class TreeNode {
var val: Int
var left: TreeNode?
var right: TreeNode?
init(_ val: Int) {
self.val = val
}
}
func inorderSuccessor(_ root: TreeNode?, _ p: TreeNode) -> TreeNode? {
if let right = p.right {
var curr = right
while let next = curr.left {
curr = next
}
return curr
}
var curr = root
var successor: TreeNode? = nil
while let node = curr {
if p.val < node.val {
successor = node
curr = node.left
} else {
curr = node.right
}
}
return successor
}
let root = TreeNode(5)
root.left = TreeNode(3)
root.right = TreeNode(7)
root.left?.left = TreeNode(2)
root.left?.right = TreeNode(4)
root.right?.right = TreeNode(8)
let p = root.left!
if let succ = inorderSuccessor(root, p) {
print(succ.val)
} else {
print("null")
}TypeScript implementation
class TreeNode {
val: number;
left: TreeNode | null;
right: TreeNode | null;
constructor(val: number, left: TreeNode | null = null, right: TreeNode | null = null) {
this.val = val;
this.left = left;
this.right = right;
}
}
function inorderSuccessor(root: TreeNode | null, p: TreeNode): TreeNode | null {
if (p.right) {
let curr = p.right;
while (curr.left) curr = curr.left;
return curr;
}
let successor: TreeNode | null = null;
while (root) {
if (p.val < root.val) {
successor = root;
root = root.left;
} else {
root = root.right;
}
}
return successor;
}
const root = new TreeNode(5,
new TreeNode(3, new TreeNode(2), new TreeNode(4)),
new TreeNode(7, null, new TreeNode(8)));
const p = root.left!;
const successor = inorderSuccessor(root, p);
console.log(successor ? successor.val : null);