Given the root
of a binary search tree (BST) and a node p
in the tree, find the in-order successor of the node p
in the BST. If the in-order successor does not exist, return null
.
The successor of a node p
is the node with the smallest key greater than p.val
.
Example 1:
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
.
Example 2:
Input: root = [5,3,6,2,4,null,null,1], p = 1 Output: 2 Explanation: 1's in-order successor node is 2. Note that the successor could be a descendant of the node.
Example 3:
Input: root = [2,1,3], p = 1 Output: 2
Constraints:
[1, 104]
.-105 <= Node.val <= 105
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
To find the inorder successor, the brute force method involves looking at all nodes in the tree. We examine each node and figure out where it fits in relation to the target node, ultimately identifying the next biggest value.
Here's how the algorithm would work step-by-step:
def inorder_successor_brute_force(root, target_node):
node_values = []
def inorder_traversal(node):
if node:
inorder_traversal(node.left)
node_values.append(node.val)
inorder_traversal(node.right)
inorder_traversal(root)
# Collect all node values.
node_values.sort()
# Find the target node's value in the sorted list.
try:
target_index = node_values.index(target_node.val)
except ValueError:
return None
# Determine if there is a next value.
if target_index + 1 < len(node_values):
successor_value = node_values[target_index + 1]
def find_node(root, value):
if not root:
return None
if root.val == value:
return root
left_result = find_node(root.left, value)
if left_result:
return left_result
return find_node(root.right, value)
# Find the node with the successor value.
return find_node(root, successor_value)
else:
# Target node had the largest value in the tree.
return None
To find the next biggest value in a special tree (a Binary Search Tree) after a specific value, we can use the structure of the tree to guide our search. Instead of checking the whole tree, we can follow a clever path that quickly leads us to the answer.
Here's how the algorithm would work step-by-step:
class TreeNode:
def __init__(self, value):
self.value = value
self.left = None
self.right = None
def inorder_successor(root, node):
potential_answer = None
while root:
if root.value > node.value:
# This node could be the answer, so store it.
potential_answer = root
root = root.left
elif root.value <= node.value:
# Go right since successor must be larger.
root = root.right
return potential_answer
Case | How to Handle |
---|---|
Null or empty BST | Return null immediately as there is no successor in an empty tree. |
Node has no inorder successor (rightmost node) | Return null when traversing up the tree and no larger parent is found. |
Node is the root of the BST | The logic to find the successor still applies regardless of the starting node's position in the tree. |
Node has a right subtree | Return the minimum value of the right subtree. |
BST contains duplicate values; node has duplicates. | Handle this case correctly by finding the smallest value larger than node.val, which might involve looking at the right subtree or ancestor nodes. |
The target node itself is null. | Return null since there is no node to find the successor of. |
BST with only one node and that is the target. | Return null, because that single node has no successor. |
Very deep BST, potential stack overflow with recursive solutions | Consider an iterative approach to avoid stack overflow issues with very large trees. |